[Qemu-devel] [PATCH] hw: fix to display correct memory size
A parenthesis placed inappropriately caused displaying wrong memory size bigger than 4GB. Signed-off-by: Yongbok Kim --- hw/mips/mips_malta.c |2 +- hw/mips/mips_r4k.c|2 +- hw/ppc/mac_oldworld.c |2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index f8d064c..23ac1ca 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -954,7 +954,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) if (ram_size > (256 << 20)) { fprintf(stderr, "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n", -((unsigned int)ram_size / (1 << 20))); +(unsigned int)(ram_size / (1 << 20))); exit(1); } memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 044f232..e8108ac 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -201,7 +201,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args) if (ram_size > (256 << 20)) { fprintf(stderr, "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n", -((unsigned int)ram_size / (1 << 20))); +(unsigned int)(ram_size / (1 << 20))); exit(1); } memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 42bb9d5..d7d1758 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -124,7 +124,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) if (ram_size > (2047 << 20)) { fprintf(stderr, "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n", -((unsigned int)ram_size / (1 << 20))); +(unsigned int)(ram_size / (1 << 20))); exit(1); } -- 1.7.4
[Qemu-devel] [PATCH] mips_malta: support up to 2GiB RAM
From: Paul Burton A Malta board can support up to 2GiB of RAM. Since the unmapped kseg0/1 regions are only 512MiB large & the latter 256MiB of those are taken up by the IO region, access to RAM beyond 256MiB must be done through a mapped region. In the case of a Linux guest this means we need to use highmem. The mainline Linux kernel does not support highmem for Malta at this time, however this can be tested using the linux-mti-3.8 kernel branch available from: git://git.linux-mips.org/pub/scm/linux-mti.git You should be able to boot a Linux kernel built from the linux-mti-3.8 branch, with CONFIG_HIGHMEM enabled, using 2GiB RAM by passing "-m 2G" to QEMU and appending the following kernel parameters: mem=256m@0x0 mem=256m@0x9000 mem=1536m@0x2000 Note that the upper half of the physical address space of a Malta mirrors the lower half (hence the 2GiB limit) except that the IO region (0x1000-0x1fff in the lower half) is not mirrored in the upper half. That is, physical addresses 0x9000-0x9fff access RAM rather than the IO region. The second mem parameter above accesses the second 256MiB of RAM through the upper half of the physical address space, making use of this property in order to avoid the IO region and use the whole 2GiB RAM. The memory setup may be seen as 'backwards' in this commit since the 'real' memory is mapped in the upper half of the physical address space and the lower half contains the aliases. On real hardware it would be typical to see the upper half of the physical address space as the alias since the bus addresses generated match the lower half of the physical address space. However since the memory accessible in the upper half of the physical address space is uninterrupted by the IO region it is easiest to map the RAM as a whole there, and functionally it makes no difference to the target code. Due to the requirements of accessing the second 256MiB of RAM through a mapping to the upper half of the physical address space it is usual for the bootloader to indicate a maximum of 256MiB memory to a kernel. This allows kernels which do not support such access to boot on systems with more than 256MiB of RAM. It is also the behaviour assumed by Linux. QEMUs small generated bootloader is modified to provide this behaviour. Signed-off-by: Paul Burton Signed-off-by: Yongbok Kim --- hw/mips/mips_malta.c | 36 1 files changed, 28 insertions(+), 8 deletions(-) diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index f8d064c..7d112ee 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -827,7 +827,8 @@ static int64_t load_kernel (void) } prom_set(prom_buf, prom_index++, "memsize"); -prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size); +prom_set(prom_buf, prom_index++, "%i", + MIN(loaderparams.ram_size, 256 << 20)); prom_set(prom_buf, prom_index++, "modetty0"); prom_set(prom_buf, prom_index++, "38400n8r"); prom_set(prom_buf, prom_index++, NULL); @@ -884,7 +885,9 @@ void mips_malta_init(QEMUMachineInitArgs *args) char *filename; pflash_t *fl; MemoryRegion *system_memory = get_system_memory(); -MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *ram_high = g_new(MemoryRegion, 1); +MemoryRegion *ram_low_preio = g_new(MemoryRegion, 1); +MemoryRegion *ram_low_postio; MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1); target_long bios_size = FLASH_SIZE; const size_t smbus_eeprom_size = 8 * 256; @@ -951,15 +954,32 @@ void mips_malta_init(QEMUMachineInitArgs *args) env = &cpu->env; /* allocate RAM */ -if (ram_size > (256 << 20)) { +if (ram_size > (2048u << 20)) { fprintf(stderr, -"qemu: Too much memory for this machine: %d MB, maximum 256 MB\n", +"qemu: Too much memory for this machine: %d MB, maximum 2048 MB\n", ((unsigned int)ram_size / (1 << 20))); exit(1); } -memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size); -vmstate_register_ram_global(ram); -memory_region_add_subregion(system_memory, 0, ram); + +/* register RAM at high address where it is undisturbed by IO */ +memory_region_init_ram(ram_high, NULL, "mips_malta.ram", ram_size); +vmstate_register_ram_global(ram_high); +memory_region_add_subregion(system_memory, 0x8000, ram_high); + +/* alias for pre IO hole access */ +memory_region_init_alias(ram_low_preio, NULL, "mips_malta_low_preio.ram", + ram_high, 0, MIN(ram_size, (256 << 20))); +memory_region_add_subregion(system_memory, 0, ram_low_preio); + +/* alias for post IO hole access, if there is enough RAM */ +if (ram_size > (
Re: [Qemu-devel] [PATCH] hw: fix to display correct memory size
Because this patch is not the critical, probably I can re-send this and the additional patches (Andreas' suggestion) as trivial patches when the 2GiB patch applied. Regards, Yongbok -Original Message- From: Alexander Graf [mailto:ag...@suse.de] Sent: 25 August 2013 17:12 To: Andreas Färber Cc: Yongbok Kim; qemu-devel@nongnu.org; Leon Alrae; aurel...@aurel32.net; critian.c...@imgtec.com Subject: Re: [Qemu-devel] [PATCH] hw: fix to display correct memory size On 23.08.2013, at 17:20, Andreas Färber wrote: > Am 23.08.2013 16:57, schrieb Yongbok Kim: >> A parenthesis placed inappropriately caused displaying wrong memory >> size bigger than 4GB. >> >> Signed-off-by: Yongbok Kim >> --- >> hw/mips/mips_malta.c |2 +- >> hw/mips/mips_r4k.c|2 +- >> hw/ppc/mac_oldworld.c |2 +- >> 3 files changed, 3 insertions(+), 3 deletions(-) > > Thanks for fixing this even beyond MIPS machines! > > In theory I would've preferred a patch using the correct format string > and dropping the unsigned int cast completely, but our RAM_ADDR_FMT > uses hexadecimal format, so: > > Reviewed-by: Andreas Färber > >> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index >> f8d064c..23ac1ca 100644 >> --- a/hw/mips/mips_malta.c >> +++ b/hw/mips/mips_malta.c >> @@ -954,7 +954,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) >> if (ram_size > (256 << 20)) { >> fprintf(stderr, >> "qemu: Too much memory for this machine: %d MB, maximum 256 >> MB\n", >> -((unsigned int)ram_size / (1 << 20))); >> +(unsigned int)(ram_size / (1 << 20))); > > Seeing that in the Malta case your other patch will trivially conflict > with this bugfix, would you have time to turn it into a series of > three patches, this being the first and adding "Cc: > qemu-sta...@nongnu.org" to its commit message for inclusion in 1.6.1, > then an additional patch replacing fprintf(stderr, "qemu: ...\n", ...) > with error_report("...", > ...) (note no trailing \n and it will also automatically prefix the > right qemu-system-mips* executable name) and finally your 2 GiB patch? Ah, saw this comment too late. Andreas' suggestions is obviously even better :). Alex
[Qemu-devel] [PATCH] target-mips: fix get_physical_address() #if 0 build error
From: James Hogan In get_physical_address() is a qemu_log() call inside an #if 0 block. When enabled the following build error is hit: target-mips/helper.c In function ‘get_physical_address’: target-mips/helper.c:220:13: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 5 has type ‘hwaddr’ [-Werror=format] Fix the *physical (hwaddr) formatting by using "%"HWADDR_PRIx instead of TARGET_FMT_lx. Signed-off-by: James Hogan Cc: Aurelien Jarno Signed-off-by: Yongbok Kim --- target-mips/helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 6feef7b..33e0e88 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -193,7 +193,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, } } #if 0 -qemu_log(TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n", +qemu_log(TARGET_FMT_lx " %d %d => %" HWADDR_PRIx " %d (%d)\n", address, rw, access_type, *physical, *prot, ret); #endif -- 1.7.4
Re: [Qemu-devel] [PATCH v3 18/21] target-mips: do not allow Status.FR=0 mode in 64-bit FPU
There is a block of code that modifies CP0_Status_rw_bitmask.CP0St_FR bit to read-writable in the same function. So effectively in case of MIPS64 R6 the bit is now R/W which shouldn't be. You need to modify or merge the code. # if defined(TARGET_MIPS64) /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */ if ((env->CP0_Config1 & (1 << CP0C1_FP)) && (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { env->CP0_Status |= (1 << CP0St_FR); } # endif Regards, Yongbok On 27/06/14 16:22, Leon Alrae wrote: > Status.FR bit must be ignored on write and read as 1 when an implementation of > Release 6 of the Architecture in which a 64-bit floating point unit is > implemented. > > Signed-off-by: Leon Alrae > --- > v3: > * remove line modifying CP0_Status_rw_bitmask as this is done while defining > CPU > --- > target-mips/translate.c |6 ++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index a804322..7cfda3d 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -17942,6 +17942,12 @@ void cpu_state_reset(CPUMIPSState *env) > } > } > #endif > +if ((env->insn_flags & ISA_MIPS32R6) && > +(env->active_fpu.fcr0 & (1 << FCR0_F64))) { > +/* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ > +env->CP0_Status |= (1 << CP0St_FR); > +} > + > compute_hflags(env); > cs->exception_index = EXCP_NONE; > }
Re: [Qemu-devel] [PATCH v3 18/21] target-mips: do not allow Status.FR=0 mode in 64-bit FPU
Correction: it is not updating the bit but checking the bit. Reviewed-by: Yongbok Kim On 02/10/14 11:21, Yongbok Kim wrote: > There is a block of code that modifies CP0_Status_rw_bitmask.CP0St_FR > bit to read-writable in the same function. > So effectively in case of MIPS64 R6 the bit is now R/W which shouldn't be. > You need to modify or merge the code. > > # if defined(TARGET_MIPS64) > /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is > writable. */ > if ((env->CP0_Config1 & (1 << CP0C1_FP)) && > (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { > env->CP0_Status |= (1 << CP0St_FR); > } > # endif > > Regards, > Yongbok > > > On 27/06/14 16:22, Leon Alrae wrote: >> Status.FR bit must be ignored on write and read as 1 when an implementation >> of >> Release 6 of the Architecture in which a 64-bit floating point unit is >> implemented. >> >> Signed-off-by: Leon Alrae >> --- >> v3: >> * remove line modifying CP0_Status_rw_bitmask as this is done while defining >> CPU >> --- >> target-mips/translate.c |6 ++ >> 1 files changed, 6 insertions(+), 0 deletions(-) >> >> diff --git a/target-mips/translate.c b/target-mips/translate.c >> index a804322..7cfda3d 100644 >> --- a/target-mips/translate.c >> +++ b/target-mips/translate.c >> @@ -17942,6 +17942,12 @@ void cpu_state_reset(CPUMIPSState *env) >> } >> } >> #endif >> +if ((env->insn_flags & ISA_MIPS32R6) && >> +(env->active_fpu.fcr0 & (1 << FCR0_F64))) { >> +/* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */ >> +env->CP0_Status |= (1 << CP0St_FR); >> +} >> + >> compute_hflags(env); >> cs->exception_index = EXCP_NONE; >> } >
Re: [Qemu-devel] [PATCH v3 16/21] target-mips: add new Floating Point instructions
Hi, Overall looking good but has issues with not freeing tcg_temps and some style problem which failed with the checkpatch.pl script. Otherwise Reviewed-by: Yongbok Kim Regards, Yongbok On 27/06/2014 16:22, Leon Alrae wrote: In terms of encoding MIPS32R6 MIN.fmt, MAX.fmt, MINA.fmt, MAXA.fmt replaced MIPS-3D RECIP1, RECIP2, RSQRT1, RSQRT2 instructions. In R6 all Floating Point instructions are supposed to be IEEE-2008 compliant i.e. FIR.HAS2008 always 1. However, QEMU softfloat for MIPS has not been updated yet. Signed-off-by: Leon Alrae --- v3: * use FOP_PROTO for new instructions and create FLOAT_RINT macro to be consistent * use TCG_CALL_NO_RWG_SE flag for float_class helper --- disas/mips.c| 22 +++ target-mips/helper.h| 20 ++ target-mips/op_helper.c | 104 +++ target-mips/translate.c | 449 ++- 4 files changed, 547 insertions(+), 48 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index e041858..6196d2e 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -1263,6 +1263,28 @@ const struct mips_opcode mips_builtin_opcodes[] = {"cache", "k,o(b)", 0x7c25, 0xfc3f, RD_b, 0, I32R6}, {"seleqz", "d,v,t",0x0035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, {"selnez", "d,v,t",0x0037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, +{"maddf.s", "D,S,T",0x4618, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"maddf.d", "D,S,T",0x46200018, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"msubf.s", "D,S,T",0x4619, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"msubf.d", "D,S,T",0x46200019, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"max.s", "D,S,T",0x461e, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"max.d", "D,S,T",0x4620001e, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"maxa.s", "D,S,T",0x461f, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"maxa.d", "D,S,T",0x4620001f, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"rint.s", "D,S", 0x461a, 0xffe0001f, WR_D|RD_S|FP_S, 0, I32R6}, +{"rint.d", "D,S", 0x4620001a, 0xffe0001f, WR_D|RD_S|FP_D, 0, I32R6}, +{"class.s", "D,S", 0x461b, 0xffe0001f, WR_D|RD_S|FP_S, 0, I32R6}, +{"class.d", "D,S", 0x4620001b, 0xffe0001f, WR_D|RD_S|FP_D, 0, I32R6}, +{"min.s", "D,S,T",0x461c, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"min.d", "D,S,T",0x4620001c, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"mina.s", "D,S,T",0x461d, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"mina.d", "D,S,T",0x4620001d, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"sel.s", "D,S,T",0x4610, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"sel.d", "D,S,T",0x46200010, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"seleqz.s", "D,S,T", 0x4614, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"seleqz.d", "D,S,T", 0x46200014, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, +{"selnez.s", "D,S,T", 0x4617, 0xffe0001f, WR_D|RD_S|RD_T|FP_S, 0, I32R6}, +{"selnez.d", "D,S,T", 0x46200017, 0xffe0001f, WR_D|RD_S|RD_T|FP_D, 0, I32R6}, {"align", "d,v,t",0x7c000220, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6}, {"dalign", "d,v,t",0x7c000224, 0xfc00063f, WR_d|RD_s|RD_t, 0, I64R6}, {"bitswap", "d,w", 0x7c20, 0xffe007ff, WR_d|RD_t,0, I32R6}, diff --git a/target-mips/helper.h b/target-mips/helper.h index 5511dfc..9020c7b 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -202,6 +202,25 @@ DEF_HELPER_2(float_cvtw_d, i32, env, i64) DEF_HELPER_3(float_addr_ps, i64, env, i64, i64) DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64) +DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32) +DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64) + +#define FOP_PROTO(op) \ +DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \ +DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64) +FOP_PROTO(maddf) +FOP_PROTO(msubf) +#undef FOP_PROTO + +#define FOP_PROTO(op)\ +DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32) \ +DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64) +FOP_PROTO(max) +FOP_PROTO(maxa) +FOP_PROTO(min) +FOP_PROTO(mina) +#undef FOP_PROTO + #define FOP_PROTO(op)
[Qemu-devel] [PATCH] target-mips: fix 34Kf configuration for DSP ASE
34Kf core does support DSP ASE. CP0_Config3 configuration for 34Kf and description are wrong. Please refer to MIPS32(R) 34Kf(TM) Processor Core Datasheet Signed-off-by: Yongbok Kim --- target-mips/translate_init.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 7cf238f..4cd9ed5 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -274,14 +274,13 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT), +.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) | + (1 << CP0C3_DSPP), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, .CCRes = 2, -/* No DSP implemented. */ .CP0_Status_rw_bitmask = 0x3678FF1F, -/* No DSP implemented. */ .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | -- 1.7.4
[Qemu-devel] [PATCH v2] target-mips: fix 34Kf configuration for DSP ASE
34Kf core does support DSP ASE. CP0_Config3 configuration for 34Kf and description are wrong. Please refer to MIPS32(R) 34Kf(TM) Processor Core Datasheet Signed-off-by: Yongbok Kim --- changes from v1: make status.MX writeable target-mips/translate_init.c |7 +++ 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 7cf238f..c45b1b2 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -274,14 +274,13 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT), +.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) | + (1 << CP0C3_DSPP), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, .CCRes = 2, -/* No DSP implemented. */ -.CP0_Status_rw_bitmask = 0x3678FF1F, -/* No DSP implemented. */ +.CP0_Status_rw_bitmask = 0x3778FF1F, .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) | (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) | (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) | -- 1.7.4
Re: [Qemu-devel] [PATCH v4 14/21] target-mips: add AUI, LSA and PCREL instruction families
I have just few minor comments. Reviewed-by: Yongbok Kim regards, Yongbok On 08/10/2014 11:55, Leon Alrae wrote: Signed-off-by: Leon Alrae --- v3: * use sextract32 instead of open coding the bit field extraction * replace _i64 with _tl in DAHI, DATI and DAUI * fix misleading LDPC comment --- disas/mips.c| 42 ++- target-mips/translate.c | 197 +--- 2 files changed, 225 insertions(+), 14 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index 8234369..091f4e2 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -407,6 +407,12 @@ struct mips_opcode "+3" UDI immediate bits 6-20 "+4" UDI immediate bits 6-25 + R6 immediates/displacements : + (adding suffix to 'o' to avoid adding new characters) + "+o" 9 bits immediate/displacement (shift = 7) + "+o1" 18 bits immediate/displacement (shift = 0) + "+o2" 19 bits immediate/displacement (shift = 0) + Other: "()" parens surrounding optional value "," separates operands @@ -1217,6 +1223,17 @@ const struct mips_opcode mips_builtin_opcodes[] = them first. The assemblers uses a hash table based on the instruction name anyhow. */ /* name,args, match, mask, pinfo, membership */ +{"lwpc","s,+o2",0xec08, 0xfc18, WR_d, 0, I32R6}, +{"lwupc", "s,+o2",0xec10, 0xfc18, WR_d, 0, I32R6}, I64R6 +{"ldpc","s,+o1",0xec18, 0xfc1c, WR_d, 0, I64R6}, +{"addiupc", "s,+o2",0xec00, 0xfc18, WR_d, 0, I32R6}, +{"auipc", "s,u", 0xec1e, 0xfc1f, WR_d, 0, I32R6}, +{"aluipc", "s,u", 0xec1f, 0xfc1f, WR_d, 0, I32R6}, +{"daui","s,t,u",0x7400, 0xfc00, RD_s|WR_t,0, I64R6}, +{"dahi","s,u", 0x0406, 0xfc1f, RD_s, 0, I64R6}, +{"dati","s,u", 0x041e, 0xfc1f, RD_s, 0, I64R6}, +{"lsa", "d,s,t",0x0005, 0xfc00073f, WR_d|RD_s|RD_t, 0, I32R6}, +{"dlsa","d,s,t",0x0015, 0xfc00073f, WR_d|RD_s|RD_t, 0, I64R6}, {"clz", "U,s", 0x0050, 0xfc1f07ff, WR_d|RD_s,0, I32R6}, {"clo", "U,s", 0x0051, 0xfc1f07ff, WR_d|RD_s,0, I32R6}, {"dclz","U,s", 0x0052, 0xfc1f07ff, WR_d|RD_s,0, I64R6}, @@ -1822,6 +1839,7 @@ const struct mips_opcode mips_builtin_opcodes[] = {"lld", "t,o(b)", 0xd000, 0xfc00, LDD|RD_b|WR_t, 0, I3 }, {"lld", "t,A(b)", 0,(int) M_LLD_AB, INSN_MACRO, 0, I3 }, {"lui", "t,u",0x3c00, 0xffe0, WR_t, 0, I1 }, +{"aui", "s,t,u",0x3c00, 0xfc00, RD_s|WR_t,0, I32R6}, {"luxc1", "D,t(b)", 0x4c05, 0xfc00f83f, LDD|WR_D|RD_t|RD_b|FP_D, 0, I5|I33|N55}, {"lw", "t,o(b)", 0x8c00, 0xfc00, LDD|RD_b|WR_t, 0, I1 }, {"lw", "t,A(b)", 0,(int) M_LW_AB,INSN_MACRO, 0, I1 }, @@ -3645,10 +3663,28 @@ print_insn_args (const char *d, break; case 'o': -delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6; -if (delta & 0x8000) { -delta |= ~0x; +switch (*(d+1)) { +case '1': +d++; +delta = l & ((1 << 18) - 1); +if (delta & 0x2) { +delta |= ~0x1; +} +break; +case '2': +d++; +delta = l & ((1 << 19) - 1); +if (delta & 0x4) { +delta |= ~0x3; +} +break; +default: +delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6; +if (delta & 0x8000) { +delta |= ~0x; +} } + (*info->fprintf_func) (info->stream, "%d", delta); break; diff --git a/target-mips/translate.c b/target-mips
Re: [Qemu-devel] [PATCH v4 21/21] target-mips: define a new generic CPU supporting MIPS64 Release 6 ISA
As this point all new R6 instructions is available, this patch should be good enough to make it able to test especially for R6 Linux user mode binaries. Reviewed-by: Yongbok Kim Regards, Yongbok On 08/10/2014 11:55, Leon Alrae wrote: Signed-off-by: Leon Alrae --- v3: * add comment to make it clear that the current definition of MIPS64R6-generic CPU does not contain support for all MIPS64R6 features yet. --- target-mips/translate_init.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 29dc2ef..67b7837 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -516,6 +516,36 @@ static const mips_def_t mips_defs[] = .mmu_type = MMU_TYPE_R4000, }, { +/* A generic CPU supporting MIPS64 Release 6 ISA. + FIXME: It does not support all the MIPS64R6 features yet. + Eventually this should be replaced by a real CPU model. */ +.name = "MIPS64R6-generic", +.CP0_PRid = 0x0001, +.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) | + (MMU_TYPE_R4000 << CP0C0_MT), +.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) | + (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) | + (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | + (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), +.CP0_Config2 = MIPS_CONFIG2, +.CP0_Config3 = MIPS_CONFIG3, +.CP0_LLAddr_rw_bitmask = 0, +.CP0_LLAddr_shift = 0, +.SYNCI_Step = 32, +.CCRes = 2, +.CP0_Status_rw_bitmask = 0x30D8, +.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | +(1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | +(0x0 << FCR0_REV), +.SEGBITS = 42, +/* The architectural limit is 59, but we have hardcoded 36 bit + in some places... +.PABITS = 59, */ /* the architectural limit */ +.PABITS = 36, +.insn_flags = CPU_MIPS64R6, +.mmu_type = MMU_TYPE_R4000, +}, +{ .name = "Loongson-2E", .CP0_PRid = 0x6302, /*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/
Re: [Qemu-devel] [PATCH v2 1/9] target-mips: add KScratch registers
Not related code changes are included. See the comment below. Other than, Reviewed-by: Yongbok Kim Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: KScratch Registers (CP0 Register 31, Selects 2 to 7) The KScratch registers are read/write registers available for scratch pad storage by kernel mode software. They are 32-bits in width for 32-bit processors and 64-bits for 64-bit processors. CP0Config4.KScrExist[2:7] bits indicate presence of CP0_KScratch1-6 registers. For Release 6, all KScratch registers are required. Signed-off-by: Leon Alrae --- target-mips/cpu.h |3 +++ target-mips/translate.c | 44 2 files changed, 47 insertions(+), 0 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 51a8331..4f6aa5b 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -136,6 +136,7 @@ typedef struct mips_def_t mips_def_t; #define MIPS_TC_MAX 5 #define MIPS_FPU_MAX 1 #define MIPS_DSP_ACC 4 +#define MIPS_KSCRATCH_NUM 6 typedef struct TCState TCState; struct TCState { @@ -229,6 +230,7 @@ struct CPUMIPSState { target_ulong CP0_EntryLo0; target_ulong CP0_EntryLo1; target_ulong CP0_Context; +target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; int32_t CP0_PageGrain; int32_t CP0_Wired; @@ -375,6 +377,7 @@ struct CPUMIPSState { uint32_t CP0_Config4; uint32_t CP0_Config4_rw_bitmask; #define CP0C4_M31 +#define CP0C4_KScrExist 16 uint32_t CP0_Config5; uint32_t CP0_Config5_rw_bitmask; #define CP0C5_M 31 diff --git a/target-mips/translate.c b/target-mips/translate.c index 6956fdd..ee18bf3 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1175,6 +1175,7 @@ typedef struct DisasContext { int bstate; target_ulong btarget; bool ulri; +int kscrexist; } DisasContext; enum { @@ -4611,6 +4612,15 @@ static inline void gen_mtc0_store64 (TCGv arg, target_ulong off) tcg_gen_st_tl(arg, cpu_env, off); } +static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg) +{ +if (ctx->insn_flags & ISA_MIPS32R6) { +tcg_gen_movi_tl(arg, 0); +} else { +tcg_gen_movi_tl(arg, ~0); +} +} + Not related with KScratch registers. It would be better to be a separate patch or as part of the patch [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register. static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) { const char *rn = "invalid"; @@ -5193,6 +5203,16 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); rn = "DESAVE"; break; +case 2 ... 7: +if (ctx->kscrexist & (1 << sel)) { +tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_KScratch[sel-2])); +tcg_gen_ext32s_tl(arg, arg); +rn = "KScratch"; +} else { +gen_mfc0_unimplemented(ctx, arg); +} +break; default: goto die; } @@ -5801,6 +5821,13 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); rn = "DESAVE"; break; +case 2 ... 7: +if (ctx->kscrexist & (1 << sel)) { +tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_KScratch[sel-2])); +rn = "KScratch"; +} +break; default: goto die; } @@ -6388,6 +6415,15 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); rn = "DESAVE"; break; +case 2 ... 7: +if (ctx->kscrexist & (1 << sel)) { +tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_KScratch[sel-2])); +rn = "KScratch"; +} else { +gen_mfc0_unimplemented(ctx, arg); +} +break; default: goto die; } @@ -6987,6 +7023,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE)); rn = "DESAVE"; break; +case 2 ... 7: +if (ctx->kscrexist & (1 << sel)) { +tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, CP0_KScratch[sel-2])); +rn = "KScratch"; +} +bre
Re: [Qemu-devel] [PATCH v2 3/9] target-mips: distinguish between data load and instruction fetch
Reviewed-by: Yongbok Kim On 08/07/2014 08:57, Leon Alrae wrote: Signed-off-by: Leon Alrae --- target-mips/helper.c | 21 ++--- 1 files changed, 10 insertions(+), 11 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 8a997e4..9871273 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -87,7 +87,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, /* Check access rights */ if (!(n ? tlb->V1 : tlb->V0)) return TLBRET_INVALID; -if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { +if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { *physical = tlb->PFN[n] | (address & (mask >> 1)); *prot = PAGE_READ; if (n ? tlb->D1 : tlb->D0) @@ -237,25 +237,28 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, case TLBRET_BADADDR: /* Reference to kernel address from user mode or supervisor mode */ /* Reference to supervisor address from user mode */ -if (rw) +if (rw == MMU_DATA_STORE) { exception = EXCP_AdES; -else +} else { exception = EXCP_AdEL; +} break; case TLBRET_NOMATCH: /* No TLB match for a mapped address */ -if (rw) +if (rw == MMU_DATA_STORE) { exception = EXCP_TLBS; -else +} else { exception = EXCP_TLBL; +} error_code = 1; break; case TLBRET_INVALID: /* TLB match with no valid bit */ -if (rw) +if (rw == MMU_DATA_STORE) { exception = EXCP_TLBS; -else +} else { exception = EXCP_TLBL; +} break; case TLBRET_DIRTY: /* TLB match but 'D' bit is cleared */ @@ -312,8 +315,6 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n", __func__, env->active_tc.PC, address, rw, mmu_idx); -rw &= 1; - /* data access */ #if !defined(CONFIG_USER_ONLY) /* XXX: put correct access by using cpu_restore_state() @@ -347,8 +348,6 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r int access_type; int ret = 0; -rw &= 1; - /* data access */ access_type = ACCESS_INT; ret = get_physical_address(env, &physical, &prot,
Re: [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
On 08/07/2014 08:57, Leon Alrae wrote: In Revision 3 of the architecture, the RI and XI bits were added to the TLB to enable more secure access of memory pages. These bits (along with the Dirty bit) allow the implementation of read-only, write-only, no-execute access policies for mapped pages. Signed-off-by: Leon Alrae --- target-mips/cpu.h | 11 +++ target-mips/helper.c| 11 ++- target-mips/op_helper.c |8 3 files changed, 29 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 4f6aa5b..5afafd7 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -30,6 +30,10 @@ struct r4k_tlb_t { uint_fast16_t V1:1; uint_fast16_t D0:1; uint_fast16_t D1:1; +uint_fast16_t XI0:1; +uint_fast16_t XI1:1; +uint_fast16_t RI0:1; +uint_fast16_t RI1:1; target_ulong PFN[2]; }; @@ -229,6 +233,13 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX00 target_ulong CP0_EntryLo0; target_ulong CP0_EntryLo1; +#if defined(TARGET_MIPS64) +# define CP0EnLo_RI 63 +# define CP0EnLo_XI 62 +#else +# define CP0EnLo_RI 31 +# define CP0EnLo_XI 30 +#endif target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; diff --git a/target-mips/helper.c b/target-mips/helper.c index 9871273..6aa8c8a 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -27,6 +27,8 @@ #include "sysemu/kvm.h" enum { +TLBRET_XI = -6, +TLBRET_RI = -5, TLBRET_DIRTY = -4, TLBRET_INVALID = -3, TLBRET_NOMATCH = -2, @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ -if (!(n ? tlb->V1 : tlb->V0)) +if (!(n ? tlb->V1 : tlb->V0)) { return TLBRET_INVALID; +} +if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { +return TLBRET_XI; +} +if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { +return TLBRET_RI; PC relative loads are allowed where execute is allowed (even though RI is 1). Rather than just return RI here have to check XI and its OP code. +} if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { *physical = tlb->PFN[n] | (address & (mask >> 1)); *prot = PAGE_READ; diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index b8d384a..3f39305 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; +tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; +tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; +tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; +tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; } @@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env) env->CP0_EntryHi = tlb->VPN | tlb->ASID; env->CP0_PageMask = tlb->PageMask; env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | +((target_ulong)tlb->RI0 << CP0EnLo_RI) | +((target_ulong)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | +((target_ulong)tlb->RI1 << CP0EnLo_RI) | +((target_ulong)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) | (tlb->PFN[1] >> 6); } Regards, Yongbok
Re: [Qemu-devel] [PATCH v2 5/9] target-mips: update PageGrain and m{t, f}c0 EntryLo{0, 1}
dm{t,f}c0_entrylo{0,1} is also added. Please reflect it in the title. I have other minor comments below. Reviewed-by: Yongbok Kim Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: PageGrain needs rw bitmask which differs between MIPS architectures. In pre-R6 if RIXI is supported, PageGrain.XIE and PageGrain.RIE are writeable, whereas in R6 they are read-only 1. Signed-off-by: Leon Alrae --- target-mips/cpu.h|4 target-mips/helper.h |5 + target-mips/op_helper.c | 25 ++--- target-mips/translate.c | 26 -- target-mips/translate_init.c |2 ++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 5afafd7..8ccb3bb 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -243,7 +243,10 @@ struct CPUMIPSState { target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; +int32_t CP0_PageGrain_rw_bitmask; int32_t CP0_PageGrain; +#define CP0PG_RIE 31 +#define CP0PG_XIE 30 int32_t CP0_Wired; int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; @@ -377,6 +380,7 @@ struct CPUMIPSState { #define CP0C3_M31 #define CP0C3_ISA_ON_EXC 16 #define CP0C3_ULRI 13 +#define CP0C3_RXI 12 #define CP0C3_DSPP 10 #define CP0C3_LPA 7 #define CP0C3_VEIC 6 diff --git a/target-mips/helper.h b/target-mips/helper.h index a127db5..e7e0c8c 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -152,6 +152,11 @@ DEF_HELPER_2(mtc0_datalo, void, env, tl) DEF_HELPER_2(mtc0_taghi, void, env, tl) DEF_HELPER_2(mtc0_datahi, void, env, tl) +#if defined(TARGET_MIPS64) +DEF_HELPER_2(dmtc0_entrylo0, void, env, i64) +DEF_HELPER_2(dmtc0_entrylo1, void, env, i64) +#endif + /* MIPS MT functions */ DEF_HELPER_2(mftgpr, tl, env, i32) DEF_HELPER_2(mftlo, tl, env, i32) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 3f39305..3579bde 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1099,9 +1099,18 @@ void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1) { /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ -env->CP0_EntryLo0 = arg1 & 0x3FFF; +target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE)); +env->CP0_EntryLo0 = (arg1 & 0x3FFF) | (rxi << (CP0EnLo_RI - 31)); rxi << (CP0EnLo_XI - 30) would be natural as CP0PG_XIE is used just above. Anyway as the result is same, you can ignore. } +#if defined(TARGET_MIPS64) +void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1) +{ It might be better to have the comments to indicate the mask is calculated based on these conditions just like mtc0_entrylo{0,1}. However you can ignore this issue. /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ +uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32); +env->CP0_EntryLo0 = (arg1 & 0x3FFF) | rxi; +} +#endif + void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1) { uint32_t mask = env->CP0_TCStatus_rw_bitmask; @@ -1266,9 +1275,18 @@ void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1) { /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ -env->CP0_EntryLo1 = arg1 & 0x3FFF; +target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE)); +env->CP0_EntryLo1 = (arg1 & 0x3FFF) | (rxi << (CP0EnLo_RI - 31)); Same here. rxi << (CP0EnLo_XI - 30) } +#if defined(TARGET_MIPS64) +void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1) +{ same here. it might need the comments. +uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32); +env->CP0_EntryLo1 = (arg1 & 0x3FFF) | rxi; +} +#endif + void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1) { env->CP0_Context = (env->CP0_Context & 0x007F) | (arg1 & ~0x007F); @@ -1285,7 +1303,8 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1) /* SmartMIPS not implemented */ /* Large physaddr (PABITS) not implemented */ /* 1k pages not implemented */ This comment is not relevant here as the function is not restricting because of the issue. However that information is still valid, you can leave the comment as it is. -env->CP0_PageGrain = 0; +env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) | + (env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask); } void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1) diff --git a/target-mips/translate.c b/target-mips/translate.c index ee18bf3..a8c8318 100644 --- a
Re: [Qemu-devel] [PATCH v2 6/9] target-mips: add new Read-Inhibit and Execute-Inhibit exceptions
Reviewed-by: Yongbok Kim Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: An Execute-Inhibit exception occurs when the virtual address of an instruction fetch matches a TLB entry whose XI bit is set. This exception type can only occur if the XI bit is implemented within the TLB and is enabled, this is denoted by the PageGrain XIE bit. An Read-Inhibit exception occurs when the virtual address of a memory load reference matches a TLB entry whose RI bit is set. This exception type can only occur if the RI bit is implemented within the TLB and is enabled, this is denoted by the PageGrain RIE bit. Signed-off-by: Leon Alrae --- target-mips/cpu.h|5 - target-mips/helper.c | 25 - 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 8ccb3bb..40ebca6 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -247,6 +247,7 @@ struct CPUMIPSState { int32_t CP0_PageGrain; #define CP0PG_RIE 31 #define CP0PG_XIE 30 +#define CP0PG_IEC 27 int32_t CP0_Wired; int32_t CP0_SRSConf0_rw_bitmask; int32_t CP0_SRSConf0; @@ -645,8 +646,10 @@ enum { EXCP_C2E, EXCP_CACHE, /* 32 */ EXCP_DSPDIS, +EXCP_TLBXI, +EXCP_TLBRI, -EXCP_LAST = EXCP_DSPDIS, +EXCP_LAST = EXCP_TLBRI, }; /* Dummy exception for conditional stores. */ #define EXCP_SC 0x100 diff --git a/target-mips/helper.c b/target-mips/helper.c index 6aa8c8a..fed28b4 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -273,7 +273,22 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, /* TLB match but 'D' bit is cleared */ exception = EXCP_LTLBL; break; - +case TLBRET_XI: +/* Execute-Inhibit Exception */ +if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { +exception = EXCP_TLBXI; +} else { +exception = EXCP_TLBL; +} +break; +case TLBRET_RI: +/* Read-Inhibit Exception */ +if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { +exception = EXCP_TLBRI; +} else { +exception = EXCP_TLBL; +} +break; } /* Raise exception */ env->CP0_BadVAddr = address; @@ -404,6 +419,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_MDMX] = "MDMX", [EXCP_C2E] = "precise coprocessor 2", [EXCP_CACHE] = "cache error", +[EXCP_TLBXI] = "TLB execute-inhibit", +[EXCP_TLBRI] = "TLB read-inhibit", }; target_ulong exception_resume_pc (CPUMIPSState *env) @@ -622,6 +639,12 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_C2E: cause = 18; goto set_EPC; +case EXCP_TLBRI: +cause = 19; +goto set_EPC; +case EXCP_TLBXI: +cause = 20; +goto set_EPC; case EXCP_MDMX: cause = 22; goto set_EPC;
Re: [Qemu-devel] [PATCH v2 7/9] target-mips: add TLBINV support
Hi Leon, As the issues below are all corrected in the PRPL already, Reviewed-by: Yongbok Kim Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: For Standard TLB configuration (Config.MT=1): TLBINV invalidates a set of TLB entries based on ASID. The virtual address is ignored in the entry match. TLB entries which have their G bit set to 1 are not modified. TLBINVF causes all entries to be invalidated. Note that this commit introduces support for Config4.IE == 3 only (i.e. TLBINV* instructions operate on entire MMU). Single TLB entry can be marked as invalid on TLB entry write by having EntryHi.EHINV set to 1. Signed-off-by: Leon Alrae --- disas/mips.c |2 + target-mips/cpu.h|7 target-mips/helper.c |2 +- target-mips/helper.h |2 + target-mips/op_helper.c | 65 + target-mips/translate.c | 22 ++ target-mips/translate_init.c |2 + 7 files changed, 94 insertions(+), 8 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index e3e253f..ff2e4b3 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -2410,6 +2410,8 @@ const struct mips_opcode mips_builtin_opcodes[] = {"tlbp","", 0x4208, 0x, INSN_TLB, 0, I1 }, {"tlbr","", 0x4201, 0x, INSN_TLB, 0, I1 }, {"tlbwi", "", 0x4202, 0x, INSN_TLB, 0, I1 }, +{"tlbinv", "", 0x4203, 0x, INSN_TLB, 0, I32 }, +{"tlbinvf", "", 0x4204, 0x, INSN_TLB, 0, I32 }, {"tlbwr", "", 0x4206, 0x, INSN_TLB, 0, I1 }, {"tlti","s,j",0x040a, 0xfc1f, RD_s|TRAP, 0, I2 }, {"tlt", "s,t",0x0032, 0xfc00, RD_s|RD_t|TRAP, 0, I2 }, diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 40ebca6..bc5 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -34,6 +34,7 @@ struct r4k_tlb_t { uint_fast16_t XI1:1; uint_fast16_t RI0:1; uint_fast16_t RI1:1; +uint_fast16_t EHINV:1; target_ulong PFN[2]; }; @@ -47,6 +48,8 @@ struct CPUMIPSTLBContext { void (*helper_tlbwr)(struct CPUMIPSState *env); void (*helper_tlbp)(struct CPUMIPSState *env); void (*helper_tlbr)(struct CPUMIPSState *env); +void (*helper_tlbinv)(struct CPUMIPSState *env); +void (*helper_tlbinvf)(struct CPUMIPSState *env); union { struct { r4k_tlb_t tlb[MIPS_TLB_MAX]; @@ -282,6 +285,7 @@ struct CPUMIPSState { target_ulong CP0_BadVAddr; int32_t CP0_Count; target_ulong CP0_EntryHi; +#define CP0EnHi_EHINV 10 int32_t CP0_Compare; int32_t CP0_Status; #define CP0St_CU3 31 @@ -393,6 +397,7 @@ struct CPUMIPSState { uint32_t CP0_Config4; uint32_t CP0_Config4_rw_bitmask; #define CP0C4_M31 +#define CP0C4_IE 29 #define CP0C4_KScrExist 16 uint32_t CP0_Config5; uint32_t CP0_Config5_rw_bitmask; @@ -528,6 +533,8 @@ void r4k_helper_tlbwi(CPUMIPSState *env); void r4k_helper_tlbwr(CPUMIPSState *env); void r4k_helper_tlbp(CPUMIPSState *env); void r4k_helper_tlbr(CPUMIPSState *env); +void r4k_helper_tlbinv(CPUMIPSState *env); +void r4k_helper_tlbinvf(CPUMIPSState *env); void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write, bool is_exec, int unused, diff --git a/target-mips/helper.c b/target-mips/helper.c index fed28b4..5d72438 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -83,7 +83,7 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, #endif /* Check ASID, virtual page number & size */ -if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) { +if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) { /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ diff --git a/target-mips/helper.h b/target-mips/helper.h index e7e0c8c..aea12a9 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -342,6 +342,8 @@ DEF_HELPER_1(tlbwi, void, env) DEF_HELPER_1(tlbwr, void, env) DEF_HELPER_1(tlbp, void, env) DEF_HELPER_1(tlbr, void, env) +DEF_HELPER_1(tlbinv, void, env) +DEF_HELPER_1(tlbinvf, void, env) DEF_HELPER_1(di, tl, env) DEF_HELPER_1(ei, tl, env) DEF_HELPER_1(eret, void, env) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 3579bde..fa96bb3 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@
Re: [Qemu-devel] [PATCH v2 9/9] target-mips: update cpu_save/cpu_load to support new registers
EHINV bit from TLB also required to be saved/ restored. Regards, Yongbok On 08/07/2014 08:57, Leon Alrae wrote: Signed-off-by: Leon Alrae --- target-mips/cpu.h |2 +- target-mips/machine.c | 14 ++ 2 files changed, 15 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 656f5ca..23bb22c 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -557,7 +557,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env); extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); -#define CPU_SAVE_VERSION 4 +#define CPU_SAVE_VERSION 5 /* MMU modes definitions. We carefully match the indices with our hflags layout. */ diff --git a/target-mips/machine.c b/target-mips/machine.c index 0496faa..576dc10 100644 --- a/target-mips/machine.c +++ b/target-mips/machine.c @@ -26,6 +26,8 @@ static void save_tc(QEMUFile *f, TCState *tc) qemu_put_betls(f, &tc->CP0_TCScheFBack); qemu_put_sbe32s(f, &tc->CP0_Debug_tcstatus); qemu_put_betls(f, &tc->CP0_UserLocal); +qemu_put_be32s(f, &tc->CP0_BadInstr); +qemu_put_be32s(f, &tc->CP0_BadInstrP); } static void save_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu) @@ -144,6 +146,9 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_sbe32s(f, &env->CP0_DataHi); qemu_put_betls(f, &env->CP0_ErrorEPC); qemu_put_sbe32s(f, &env->CP0_DESAVE); +for (i = 0; i < MIPS_KSCRATCH_NUM; i++) { +qemu_put_betls(f, &env->CP0_KScratch[i]); +} /* Save inactive TC state */ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) @@ -177,6 +182,10 @@ static void load_tc(QEMUFile *f, TCState *tc, int version_id) if (version_id >= 4) { qemu_get_betls(f, &tc->CP0_UserLocal); } +if (version_id >= 5) { +qemu_get_be32s(f, &tc->CP0_BadInstr); +qemu_get_be32s(f, &tc->CP0_BadInstrP); +} } static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu) @@ -301,6 +310,11 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_sbe32s(f, &env->CP0_DataHi); qemu_get_betls(f, &env->CP0_ErrorEPC); qemu_get_sbe32s(f, &env->CP0_DESAVE); +if (version_id >= 5) { +for (i = 0; i < MIPS_KSCRATCH_NUM; i++) { +qemu_get_betls(f, &env->CP0_KScratch[i]); +} +} /* Load inactive TC state */ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
Re: [Qemu-devel] [PATCH 1/6] target-mips: add Config5.SBRI
Please update message body as it also adds dm{f,t}c0 for config{4,5}. See the comment below. Reviewed-by: Yongbok Kim Regards, Yongbok On 14/07/2014 17:19, Leon Alrae wrote: SDBBP instruction Reserved Instruction control. The purpose of this field is to restrict availability of SDBBP to kernel mode operation. If the bit is set then SDBBP instruction can only be executed in kernel mode. User execution of SDBBP will cause a Reserved Instruction exception. Signed-off-by: Leon Alrae --- target-mips/cpu.h | 11 +-- target-mips/translate.c | 24 +++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 23bb22c..2a762d2 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -410,6 +410,7 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA28 #define CP0C5_MSAEn 27 +#define CP0C5_SBRI 6 #define CP0C5_UFR2 #define CP0C5_NFExists 0 int32_t CP0_Config6; @@ -461,7 +462,7 @@ struct CPUMIPSState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags;/* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0xC07FF +#define MIPS_HFLAG_TMASK 0x2C07FF #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -504,6 +505,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_DSPR2 0x8 /* Enable access to MIPS DSPR2 resources. */ /* Extra flag about HWREna register. */ #define MIPS_HFLAG_HWRENA_ULR 0x10 /* ULR bit from HWREna is set. */ +#define MIPS_HFLAG_SBRI 0x20 /* R6 SDBBP causes RI excpt. in user mode */ also in supervisor mode. :) target_ulong btarget;/* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -759,7 +761,8 @@ static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); + MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | + MIPS_HFLAG_SBRI); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -795,6 +798,10 @@ static inline void compute_hflags(CPUMIPSState *env) if (env->CP0_Status & (1 << CP0St_FR)) { env->hflags |= MIPS_HFLAG_F64; } +if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) && +(env->CP0_Config5 & (1 << CP0C5_SBRI))) { +env->hflags |= MIPS_HFLAG_SBRI; +} if (env->insn_flags & ASE_DSPR2) { /* Enables access MIPS DSP resources, now our cpu is DSP ASER2, so enable to access DSPR2 resources. */ diff --git a/target-mips/translate.c b/target-mips/translate.c index b931574..d0f695a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6273,6 +6273,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3)); rn = "Config3"; break; +case 4: +gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4)); +rn = "Config4"; +break; +case 5: +gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); +rn = "Config5"; +break; /* 6,7 are implementation dependent */ case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); @@ -6891,6 +6899,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* ignored */ rn = "Config3"; break; +case 4: +/* currently ignored */ +rn = "Config4"; +break; +case 5: +gen_helper_mtc0_config5(cpu_env, arg); +rn = "Config5"; +/* Stop translation as we may have switched the execution mode */ +ctx->bstate = BS_STOP; +break; /* 6,7 are implementation dependent */ default: rn = "Invalid config selector"; @@ -15886,7 +15904,11 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) } break; case R6_OPC_SDBBP: -generate_exception(ctx, EXCP_DBp); +if (ctx->hflags & MIPS_HFLAG_SBRI) { +generate_exception(ctx, EXCP_RI); +} else { +generate_exception(ctx, EXCP_DBp); +} break; #if defined(TARGET_MIPS64) case OPC_DLSA:
Re: [Qemu-devel] [PATCH 3/6] target-mips: CP0_Status.CU0 no longer allows the user to access CP0
Reviewed-by: Yongbok Kim Regards, Yongbok On 14/07/2014 17:19, Leon Alrae wrote: Signed-off-by: Leon Alrae --- target-mips/cpu.h |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index a35ab9d..b981ec7 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -789,7 +789,8 @@ static inline void compute_hflags(CPUMIPSState *env) } } #endif -if ((env->CP0_Status & (1 << CP0St_CU0)) || +if (((env->CP0_Status & (1 << CP0St_CU0)) && + !(env->insn_flags & ISA_MIPS32R6)) || !(env->hflags & MIPS_HFLAG_KSU)) { env->hflags |= MIPS_HFLAG_CP0; }
Re: [Qemu-devel] [PATCH 4/6] target-mips: add restrictions for possible values in registers
On 14/07/2014 17:19, Leon Alrae wrote: In Release 6 not all the values are allowed to be written to a register. If the value is not valid or unsupported then it should stay unchanged. For pre-R6 the existing behaviour has been changed only for CP0_Index register as the current implementation does not seem to be correct - it looks like it tries to limit the input value but the limit is higher than the actual number of tlb entries. Signed-off-by: Leon Alrae --- target-mips/op_helper.c | 63 ++ 1 files changed, 46 insertions(+), 17 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 431f3a1..4be435c 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -959,14 +959,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel) void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1) { -int num = 1; -unsigned int tmp = env->tlb->nb_tlb; - -do { -tmp >>= 1; -num <<= 1; -} while (tmp); -env->CP0_Index = (env->CP0_Index & 0x8000) | (arg1 & (num - 1)); +uint32_t index_p = env->CP0_Index & 0x8000; +uint32_t tlb_index = arg1 & 0x7fff; +if (tlb_index < env->tlb->nb_tlb) { +if (env->insn_flags & ISA_MIPS32R6) { +index_p |= arg1 & 0x8000; +} +env->CP0_Index = index_p | tlb_index; +} Agree to restrict index for pre R6 as well. It is UNDEFINED and software shouldn't rely on the undefined behaviour. } void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1) @@ -1294,8 +1294,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1) { -/* 1k pages not implemented */ This comment is still valid but it is appeared several times in the code already. Agreed to remove the comment here. -env->CP0_PageMask = arg1 & (0x1FFF & (TARGET_PAGE_MASK << 1)); +uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1); +if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) || +(mask == 0x || mask == 0x0003 || mask == 0x000F || + mask == 0x003F || mask == 0x00FF || mask == 0x03FF || + mask == 0x0FFF || mask == 0x3FFF || mask == 0x)) { +env->CP0_PageMask = arg1 & (0x1FFF & (TARGET_PAGE_MASK << 1)); +} } void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1) @@ -1309,7 +1314,13 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1) void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1) { -env->CP0_Wired = arg1 % env->tlb->nb_tlb; +if (env->insn_flags & ISA_MIPS32R6) { +if (arg1 < env->tlb->nb_tlb) { +env->CP0_Wired = arg1; Wired field should be compared with Limit field (and as a result, number of entries in the TLB). +} +} else { +env->CP0_Wired = arg1 % env->tlb->nb_tlb; +} } void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1) @@ -1368,11 +1379,14 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1) } /* 1k pages not implemented */ -val = arg1 & mask; #if defined(TARGET_MIPS64) -val &= env->SEGMask; +if ((env->insn_flags & ISA_MIPS32R6) && extract64(arg1, 62, 2) == 0x2) { +mask &= ~(0x3ull << 62); If Config0_AT = 1, R field is restricted for 1 as well. +} +mask &= env->SEGMask; #endif old = env->CP0_EntryHi; +val = (arg1 & mask) | (old & ~mask); env->CP0_EntryHi = val; if (env->CP0_Config3 & (1 << CP0C3_MT)) { sync_c0_entryhi(env, env->current_tc); @@ -1402,6 +1416,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1) uint32_t val, old; uint32_t mask = env->CP0_Status_rw_bitmask; +if (env->insn_flags & ISA_MIPS32R6) { +if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) { +mask &= ~(3 << CP0St_KSU); +} +mask &= ~(0x0018 & arg1); +} + val = arg1 & mask; old = env->CP0_Status; env->CP0_Status = (env->CP0_Status & ~mask) | val; @@ -1457,6 +1478,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1) if (cpu->insn_flags & ISA_MIPS32R2) { mask |= 1 << CP0Ca_DC; } +if (cpu->insn_flags & ISA_MIPS32R6) { +mask &= ~((1 << CP0Ca_WP) & arg1); +} cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask); @@ -2381,8 +2405,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) } break; case 25: -if (arg1 & 0xff00) +if (env->insn_flags & ISA_MIPS32R6 || arg1 & 0xff00) { return; +} env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017f) | ((arg1 & 0xfe) << 24) | ((arg1 & 0x1) << 23); break; @@ -2398,9 +2423,13 @@ void helper_ctc1(CPUMIPSState *
Re: [Qemu-devel] [PATCH 5/6] target-mips: correctly handle access to unimplemented CP0 register
On 14/07/2014 17:19, Leon Alrae wrote: Release 6 limits the number of cases where software can cause UNDEFINED or UNPREDICTABLE behaviour. In this case, when accessing reserved / unimplemented CP0 register, writes are ignored and reads return 0. In pre-R6 the behaviour is not specified, but generating RI exception is not what the real HW does. Additionally, remove CP0 Random register as it became reserved in Release 6. Signed-off-by: Leon Alrae --- target-mips/translate.c | 546 +++ 1 files changed, 264 insertions(+), 282 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 4ed81fe..cd20f35 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4627,6 +4627,13 @@ static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg) } } +#define CP0_CHECK(c)\ +do {\ +if (!(c)) { \ +goto cp0_unimplemented; \ +} \ +} while (0) + static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) { const char *rn = "invalid"; @@ -4642,67 +4649,68 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "Index"; break; case 1: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpcontrol(arg, cpu_env); rn = "MVPControl"; break; case 2: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf0(arg, cpu_env); rn = "MVPConf0"; break; case 3: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_mvpconf1(arg, cpu_env); rn = "MVPConf1"; break; default: -goto die; +goto cp0_unimplemented; } break; case 1: switch (sel) { case 0: +CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6)); gen_helper_mfc0_random(arg, cpu_env); rn = "Random"; break; case 1: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl)); rn = "VPEControl"; break; case 2: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0)); rn = "VPEConf0"; break; case 3: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1)); rn = "VPEConf1"; break; case 4: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask)); rn = "YQMask"; break; case 5: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule)); rn = "VPESchedule"; break; case 6: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack)); rn = "VPEScheFBack"; break; case 7: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt)); rn = "VPEOpt"; break; default: -goto die; +goto cp0_unimplemented; } break; case 2: @@ -4722,42 +4730,42 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) rn = "EntryLo0"; break; case 1: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcstatus(arg, cpu_env); rn = "TCStatus"; break; case 2: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcbind(arg, cpu_env); rn = "TCBind"; break; case 3: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT); gen_helper_mfc0_tcrestart(arg, cpu_env); rn = "TCRestart"; break; case 4: -check_insn(ctx, ASE_MT); +CP0_CHECK(ctx->insn_flags & ASE_MT);
Re: [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot
/* OPC_BNEC */ -tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1); +tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs); } } break; case OPC_BEQZC: -tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); +tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); break; case OPC_BNEZC: -tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); +tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs); break; default: MIPS_INVAL("Compact conditional branch/jump"); @@ -15831,12 +15853,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, } /* Generating branch here as compact branches don't have delay slot */ -/* TODO: implement forbidden slot */ -gen_goto_tb(ctx, 1, ctx->pc + 4); -gen_set_label(l1); -gen_goto_tb(ctx, 0, ctx->btarget); +gen_goto_tb(ctx, 1, ctx->btarget); +gen_set_label(fs); + +ctx->hflags |= MIPS_HFLAG_FBNSLOT; MIPS_DEBUG("Compact conditional branch"); -ctx->bstate = BS_BRANCH; } out: @@ -16054,6 +16075,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) op1 = MASK_SPECIAL(ctx->opcode); switch (op1) { case OPC_SLL: /* Shift with immediate */ +if (sa == 5 && rd == 0 && +rs == 0 && rt == 0) { /* PAUSE */ +if (ctx->insn_flags & ISA_MIPS32R6 && +ctx->hflags & MIPS_HFLAG_BMASK) { +MIPS_DEBUG("CTI in delay / forbidden slot"); +generate_exception(ctx, EXCP_RI); +break; +} +} +/* Fallthrough */ case OPC_SRA: gen_shift_imm(ctx, op1, rd, rt, sa); break; @@ -17647,7 +17678,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int num_insns; int max_insns; int insn_bytes; -int is_delay; +int is_slot; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -17712,7 +17743,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); -is_delay = ctx.hflags & MIPS_HFLAG_BMASK; +is_slot = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { ctx.opcode = cpu_ldl_code(env, ctx.pc); insn_bytes = 4; @@ -17729,7 +17760,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, break; } -if (is_delay) { +if (is_slot) { gen_branch(&ctx, insn_bytes); } ctx.pc += insn_bytes; Comments on 4155 , 7839 and 15616 are also required changes to indicate it might be delay or forbidden slot. Otherwise, Reviewed-by: Yongbok Kim Regards, Yongbok
Re: [Qemu-devel] [PATCH 6/6] target-mips: enable features in MIPS64R6-generic CPU
On 14/07/2014 17:19, Leon Alrae wrote: Signed-off-by: Leon Alrae --- target-mips/translate_init.c | 11 +-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index bcfc46a..0b70d05 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -519,7 +519,7 @@ static const mips_def_t mips_defs[] = }, { /* A generic CPU supporting MIPS64 Release 6 ISA. - FIXME: It does not support all the MIPS64R6 features yet. + FIXME: Support IEEE 754-2008 FP and misaligned memory accesses. Eventually this should be replaced by a real CPU model. */ .name = "MIPS64R6-generic", .CP0_PRid = 0x0001, @@ -530,12 +530,19 @@ static const mips_def_t mips_defs[] = (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) | (0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3, +.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) | + (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M), +.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | + (3 << CP0C4_IE) | (1 << CP0C4_M), +.CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI), .CP0_LLAddr_rw_bitmask = 0, .CP0_LLAddr_shift = 0, .SYNCI_Step = 32, .CCRes = 2, .CP0_Status_rw_bitmask = 0x30D8, +.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | + (1U << CP0PG_RIE), +.CP0_PageGrain_rw_bitmask = 0, .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV), Reviewed-by: Yongbok Kim Regards, Yongbok
Re: [Qemu-devel] [PATCH 01/20] target-mips: add MSA defines and data structure
Hi, On 22/10/2014 12:35, James Hogan wrote: +union wr_t { +int8_t b[MSA_WRLEN/8]; +int16_t h[MSA_WRLEN/16]; +int32_t w[MSA_WRLEN/32]; +int64_t d[MSA_WRLEN/64]; This is incorrect on a big endian host. The least significant bits of the lowest indexed element should always alias. With a compiler for little endian this will work fine since b[0] will alias the least significant bits of h[0], w[0], and d[0], whereas with a compiler for big endian, b[0] will alias the upper byte of h[0], w[0], and d[0]. Yes it wouldn't work for a big endian host. However this MSA feature has been fully verified for big and little endian targets on a little endian host. I can see that the dsp_helper.c has similar problem as well. MSA could be forcibly turned off in a big endian host or might be leaved as it is just like DSP. If we need to implement for big endian host it would take longer time... What do you guys think about that? Regards, Yongbok
Re: [Qemu-devel] [PATCH v2 4/9] target-mips: add RI and XI fields to TLB entry
On 24/10/2014 15:16, Leon Alrae wrote: On 15/10/2014 13:24, Yongbok Kim wrote: On 08/07/2014 08:57, Leon Alrae wrote: In Revision 3 of the architecture, the RI and XI bits were added to the TLB to enable more secure access of memory pages. These bits (along with the Dirty bit) allow the implementation of read-only, write-only, no-execute access policies for mapped pages. Signed-off-by: Leon Alrae --- target-mips/cpu.h | 11 +++ target-mips/helper.c| 11 ++- target-mips/op_helper.c |8 3 files changed, 29 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 4f6aa5b..5afafd7 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -30,6 +30,10 @@ struct r4k_tlb_t { uint_fast16_t V1:1; uint_fast16_t D0:1; uint_fast16_t D1:1; +uint_fast16_t XI0:1; +uint_fast16_t XI1:1; +uint_fast16_t RI0:1; +uint_fast16_t RI1:1; target_ulong PFN[2]; }; @@ -229,6 +233,13 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX00 target_ulong CP0_EntryLo0; target_ulong CP0_EntryLo1; +#if defined(TARGET_MIPS64) +# define CP0EnLo_RI 63 +# define CP0EnLo_XI 62 +#else +# define CP0EnLo_RI 31 +# define CP0EnLo_XI 30 +#endif target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; diff --git a/target-mips/helper.c b/target-mips/helper.c index 9871273..6aa8c8a 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -27,6 +27,8 @@ #include "sysemu/kvm.h" enum { +TLBRET_XI = -6, +TLBRET_RI = -5, TLBRET_DIRTY = -4, TLBRET_INVALID = -3, TLBRET_NOMATCH = -2, @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ -if (!(n ? tlb->V1 : tlb->V0)) +if (!(n ? tlb->V1 : tlb->V0)) { return TLBRET_INVALID; +} +if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { +return TLBRET_XI; +} +if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { +return TLBRET_RI; PC relative loads are allowed where execute is allowed (even though RI is 1). Rather than just return RI here have to check XI and its OP code. This is true only for MIPS16 PC-relative loads. New R6 PC-relative loads do cause TLBRI exceptions. Thus in context of Release 6 current implementation is correct. I agree this will need to be corrected for MIPS16, but not necessarily in this patchset. Regards, Leon Agreed. Regards, Yongbok
Re: [Qemu-devel] [PATCH v3 04/15] target-mips: add RI and XI fields to TLB entry
On 24/10/2014 13:42, Leon Alrae wrote: In Revision 3 of the architecture, the RI and XI bits were added to the TLB to enable more secure access of memory pages. These bits (along with the Dirty bit) allow the implementation of read-only, write-only, no-execute access policies for mapped pages. Signed-off-by: Leon Alrae --- target-mips/cpu.h | 11 +++ target-mips/helper.c| 11 ++- target-mips/op_helper.c | 8 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 91e781e..13f3a48 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -30,6 +30,10 @@ struct r4k_tlb_t { uint_fast16_t V1:1; uint_fast16_t D0:1; uint_fast16_t D1:1; +uint_fast16_t XI0:1; +uint_fast16_t XI1:1; +uint_fast16_t RI0:1; +uint_fast16_t RI1:1; target_ulong PFN[2]; }; @@ -229,6 +233,13 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX00 target_ulong CP0_EntryLo0; target_ulong CP0_EntryLo1; +#if defined(TARGET_MIPS64) +# define CP0EnLo_RI 63 +# define CP0EnLo_XI 62 +#else +# define CP0EnLo_RI 31 +# define CP0EnLo_XI 30 +#endif target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; diff --git a/target-mips/helper.c b/target-mips/helper.c index 1c9e69d..49187a3 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -27,6 +27,8 @@ #include "sysemu/kvm.h" enum { +TLBRET_XI = -6, +TLBRET_RI = -5, TLBRET_DIRTY = -4, TLBRET_INVALID = -3, TLBRET_NOMATCH = -2, @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ -if (!(n ? tlb->V1 : tlb->V0)) +if (!(n ? tlb->V1 : tlb->V0)) { return TLBRET_INVALID; +} +if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { +return TLBRET_XI; +} +if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { +return TLBRET_RI; +} if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { *physical = tlb->PFN[n] | (address & (mask >> 1)); *prot = PAGE_READ; diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 5204ed8..ca65ab4 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; +tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; +tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; +tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; +tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; } @@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env) env->CP0_EntryHi = tlb->VPN | tlb->ASID; env->CP0_PageMask = tlb->PageMask; env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | +((target_ulong)tlb->RI0 << CP0EnLo_RI) | +((target_ulong)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | +((target_ulong)tlb->RI1 << CP0EnLo_RI) | +((target_ulong)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) | (tlb->PFN[1] >> 6); } Reviewed-by: Yongbok Kim Regards, Yongbok
[Qemu-devel] [PATCH v2 04/20] target-mips: add 16, 64 bit load and store
Signed-off-by: Yongbok Kim --- target-mips/op_helper.c |7 +++ 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 7cbf4cf..e878442 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -90,10 +90,10 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ } \ } #endif +HELPER_LD(lbu, ldub, uint8_t) +HELPER_LD(lhu, lduw, uint16_t) HELPER_LD(lw, ldl, int32_t) -#ifdef TARGET_MIPS64 HELPER_LD(ld, ldq, int64_t) -#endif #undef HELPER_LD #if defined(CONFIG_USER_ONLY) @@ -118,10 +118,9 @@ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ } #endif HELPER_ST(sb, stb, uint8_t) +HELPER_ST(sh, stw, uint16_t) HELPER_ST(sw, stl, uint32_t) -#ifdef TARGET_MIPS64 HELPER_ST(sd, stq, uint64_t) -#endif #undef HELPER_ST target_ulong helper_clo (target_ulong arg1) -- 1.7.4
[Qemu-devel] [PATCH v2 00/20] target-mips: add MSA module
The following patchset implements MIPS SIMD Architecture module. MSA adds new instructions to MIPS Architecture that allow efficient parallel processing of vector operations. For more information refer to: MIPS Architecture Reference Manual Volume IV-j: The MIPS32 SIMD Architecture Module The document (MD00867) is available at: http://www.imgtec.com/mips/architectures/simd.asp The MSA floating-point is compliant with the IEEE Standard for Floating-Point Arithmetic 754TM-2008. However this patchset is not set up with the IEEE-2008 option as QEMU softfloat for MIPS has not been updated yet. v2: * fixes for Leon's and James' comments * rebased top of R6 patchset * Code refactored mainly for msa_helper.c Yongbok Kim (20): target-mips: add MSA defines and data structure target-mips: add MSA exceptions target-mips: remove duplicated mips/ieee mapping function target-mips: add 16, 64 bit load and store target-mips: stop translation after ctc1 target-mips: add MSA opcode enum target-mips: add msa_reset(), global msa register target-mips: add msa_helper.c target-mips: add MSA branch instructions target-mips: add MSA I8 format instructions target-mips: add MSA I5 format instruction target-mips: add MSA BIT format instructions target-mips: add MSA 3R format instructions target-mips: add MSA ELM format instructions target-mips: add MSA 3RF format instructions target-mips: add MSA VEC/2R format instructions target-mips: add MSA 2RF format instructions target-mips: add MSA MI10 format instructions disas/mips.c: disassemble MSA instructions target-mips: add MSA support to mips32r5-generic disas/mips.c | 716 +- target-mips/Makefile.objs|2 +- target-mips/cpu.h| 56 +- target-mips/gdbstub.c|7 - target-mips/helper.c | 10 + target-mips/helper.h | 184 +++ target-mips/mips-defs.h |1 + target-mips/msa_helper.c | 3461 ++ target-mips/op_helper.c | 89 +- target-mips/translate.c | 1653 +++-- target-mips/translate_init.c | 39 +- 11 files changed, 6081 insertions(+), 137 deletions(-) create mode 100644 target-mips/msa_helper.c -- 1.7.4
[Qemu-devel] [PATCH v2 02/20] target-mips: add MSA exceptions
add MSA exceptions Signed-off-by: Yongbok Kim --- target-mips/helper.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index c92b25c..3a93c20 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -426,6 +426,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", [EXCP_TLBXI] = "TLB execute-inhibit", [EXCP_TLBRI] = "TLB read-inhibit", +[EXCP_MSADIS] = "MSA disabled", +[EXCP_MSAFPE] = "MSA floating point", }; target_ulong exception_resume_pc (CPUMIPSState *env) @@ -667,6 +669,10 @@ void mips_cpu_do_interrupt(CPUState *cs) cause = 13; update_badinstr = 1; goto set_EPC; +case EXCP_MSAFPE: +cause = 14; +update_badinstr = 1; +goto set_EPC; case EXCP_FPE: cause = 15; update_badinstr = 1; @@ -681,6 +687,10 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_TLBXI: cause = 20; goto set_EPC; +case EXCP_MSADIS: +cause = 21; +update_badinstr = 1; +goto set_EPC; case EXCP_MDMX: cause = 22; goto set_EPC; -- 1.7.4
[Qemu-devel] [PATCH v2 12/20] target-mips: add MSA BIT format instructions
add MSA BIT format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 13 +++ target-mips/msa_helper.c | 197 ++ target-mips/translate.c | 85 3 files changed, 295 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 585eaa9..b5f171c 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -771,3 +771,16 @@ DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) + +DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index ffdde07..da43439 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -256,3 +256,200 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } } + +/* Data format bit position and unsigned values */ +#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) + +static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return arg1 << b_arg2; +} + +static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return arg1 >> b_arg2; +} + +static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +int32_t b_arg2 = BIT_POSITION(arg2, df); +return u_arg1 >> b_arg2; +} + +static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} + +static inline int64_t msa_bset_df(uint32_t df, int64_t arg1, +int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_dest = UNSIGNED(dest, df); +int32_t sh_d = BIT_POSITION(arg2, df) + 1; +int32_t sh_a = DF_BITS(df) - sh_d; +if (sh_d == DF_BITS(df)) { +return u_arg1; +} else { +return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df); +} +} + +static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_dest = UNSIGNED(dest, df); +int32_t sh_d = BIT_POSITION(arg2, df) + 1; +int32_t sh_a = DF_BITS(df) - sh_d; +if (sh_d == DF_BITS(df)) { +return u_arg1; +} else { +return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df); +} +} + +static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m) +{ +return arg < M_MIN_INT(m+1) ? M_MIN_INT(m+1) : + arg > M_MAX_INT(m+1) ? M_MAX_INT(m+1) : + arg; +} + +static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m) +{ +uint64_t u_arg = UNSIGNED(arg, df); +return u_arg < M_MAX_UINT(m+1) ? u_arg : + M_MAX_UINT(m+1); +} + +static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +if (b_arg2 == 0) { +return arg1; +} else { +int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1; +return (arg1 >> b_arg2) + r_bit; +} +} + +static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +int32_t b_arg2 = BIT_POSITION(arg2, df); +if (b_arg2 == 0
[Qemu-devel] [PATCH v2 06/20] target-mips: add MSA opcode enum
add MSA opcode enum Reviewed-by: James Hogan Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- target-mips/translate.c | 245 +++ 1 files changed, 245 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b388ba5..555f89b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -137,6 +137,8 @@ enum { OPC_JIALC= (0x3E << 26), /* MDMX ASE specific */ OPC_MDMX = (0x1E << 26), +/* MSA ASE, same as MDMX */ +OPC_MSA = OPC_MDMX, /* Cache and prefetch */ OPC_CACHE= (0x2F << 26), OPC_PREF = (0x33 << 26), @@ -934,6 +936,8 @@ enum { OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, +OPC_BZ_V = (0x0B << 21) | OPC_CP1, +OPC_BNZ_V= (0x0F << 21) | OPC_CP1, OPC_S_FMT= (FMT_S << 21) | OPC_CP1, OPC_D_FMT= (FMT_D << 21) | OPC_CP1, OPC_E_FMT= (FMT_E << 21) | OPC_CP1, @@ -943,6 +947,14 @@ enum { OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, OPC_BC1EQZ = (0x09 << 21) | OPC_CP1, OPC_BC1NEZ = (0x0D << 21) | OPC_CP1, +OPC_BZ_B = (0x18 << 21) | OPC_CP1, +OPC_BZ_H = (0x19 << 21) | OPC_CP1, +OPC_BZ_W = (0x1A << 21) | OPC_CP1, +OPC_BZ_D = (0x1B << 21) | OPC_CP1, +OPC_BNZ_B= (0x1C << 21) | OPC_CP1, +OPC_BNZ_H= (0x1D << 21) | OPC_CP1, +OPC_BNZ_W= (0x1E << 21) | OPC_CP1, +OPC_BNZ_D= (0x1F << 21) | OPC_CP1, }; #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) @@ -1103,6 +1115,239 @@ enum { OPC_NMSUB_PS= 0x3E | OPC_CP3, }; +/* MSA Opcodes */ +#define MASK_MSA_MINOR(op)(MASK_OP_MAJOR(op) | (op & 0x3F)) +enum { +OPC_MSA_I8_00 = 0x00 | OPC_MSA, +OPC_MSA_I8_01 = 0x01 | OPC_MSA, +OPC_MSA_I8_02 = 0x02 | OPC_MSA, +OPC_MSA_I5_06 = 0x06 | OPC_MSA, +OPC_MSA_I5_07 = 0x07 | OPC_MSA, +OPC_MSA_BIT_09 = 0x09 | OPC_MSA, +OPC_MSA_BIT_0A = 0x0A | OPC_MSA, +OPC_MSA_3R_0D = 0x0D | OPC_MSA, +OPC_MSA_3R_0E = 0x0E | OPC_MSA, +OPC_MSA_3R_0F = 0x0F | OPC_MSA, +OPC_MSA_3R_10 = 0x10 | OPC_MSA, +OPC_MSA_3R_11 = 0x11 | OPC_MSA, +OPC_MSA_3R_12 = 0x12 | OPC_MSA, +OPC_MSA_3R_13 = 0x13 | OPC_MSA, +OPC_MSA_3R_14 = 0x14 | OPC_MSA, +OPC_MSA_3R_15 = 0x15 | OPC_MSA, +OPC_MSA_ELM = 0x19 | OPC_MSA, +OPC_MSA_3RF_1A = 0x1A | OPC_MSA, +OPC_MSA_3RF_1B = 0x1B | OPC_MSA, +OPC_MSA_3RF_1C = 0x1C | OPC_MSA, +OPC_MSA_VEC = 0x1E | OPC_MSA, + +/* MI10 instruction */ +OPC_LD_B= (0x20) | OPC_MSA, +OPC_LD_H= (0x21) | OPC_MSA, +OPC_LD_W= (0x22) | OPC_MSA, +OPC_LD_D= (0x23) | OPC_MSA, +OPC_ST_B= (0x24) | OPC_MSA, +OPC_ST_H= (0x25) | OPC_MSA, +OPC_ST_W= (0x26) | OPC_MSA, +OPC_ST_D= (0x27) | OPC_MSA, +}; + +enum { +/* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ +OPC_ADDVI_df= (0x0 << 23) | OPC_MSA_I5_06, +OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, +OPC_SUBVI_df= (0x1 << 23) | OPC_MSA_I5_06, +OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, +OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, +OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, +OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, +OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, +OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, +OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, +OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, +OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, + +/* I8 instruction */ +OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, +OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, +OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, +OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, +OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, +OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, +OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, +OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, +OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02, +OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00, + +/* VEC/2R/2RF instruction */ +OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC, +OPC_OR_V= (0x01 << 21) | OPC_MSA_VEC, +OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC, +OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC, +OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC, +OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC, +OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC, + +OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC, +OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC, + +/* 2R instruction df(bits
[Qemu-devel] [PATCH v2 01/20] target-mips: add MSA defines and data structure
add defines and data structure for MIPS SIMD Architecture Signed-off-by: Yongbok Kim --- target-mips/cpu.h | 52 +- target-mips/mips-defs.h |1 + target-mips/op_helper.c |1 + 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 3b975eb..fb5abda 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -58,12 +58,32 @@ struct CPUMIPSTLBContext { }; #endif +/* MSA Context */ +#define MSA_WRLEN (128) + +enum CPUMIPSMSADataFormat { +DF_BYTE = 0, +DF_HALF, +DF_WORD, +DF_DOUBLE +}; + +typedef union wr_t wr_t; +union wr_t { +int8_t b[MSA_WRLEN/8]; +int16_t h[MSA_WRLEN/16]; +int32_t w[MSA_WRLEN/32]; +int64_t d[MSA_WRLEN/64]; +}; + typedef union fpr_t fpr_t; union fpr_t { float64 fd; /* ieee double precision */ float32 fs[2];/* ieee single precision */ uint64_t d;/* binary double fixed-point */ uint32_t w[2]; /* binary single fixed-point */ +/* FPU/MSA register mapping is not tested on big-endian hosts. */ +wr_t wr; /* vector data */ }; /* define FP_ENDIAN_IDX to access the same location * in the fpr_t union regardless of the host endianness @@ -177,6 +197,21 @@ struct TCState { target_ulong CP0_TCScheFBack; int32_t CP0_Debug_tcstatus; target_ulong CP0_UserLocal; + +int32_t msacsr; + +#define MSACSR_FS 24 +#define MSACSR_FS_MASK (1 << MSACSR_FS) +#define MSACSR_NX 18 +#define MSACSR_NX_MASK (1 << MSACSR_NX) +#define MSACSR_Flags2 +#define MSACSR_CEF_MASK (0x << MSACSR_Flags) +#define MSACSR_RM 0 +#define MSACSR_RM_MASK (0x3 << MSACSR_RM) +#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \ +MSACSR_FS_MASK) + +float_status msa_fp_status; }; typedef struct CPUMIPSState CPUMIPSState; @@ -192,6 +227,10 @@ struct CPUMIPSState { target_ulong SEGMask; target_ulong PAMask; +int32_t msair; +#define MSAIR_ProcID8 +#define MSAIR_Rev 0 + int32_t CP0_Index; /* CP0_MVP* are per MVP registers. */ int32_t CP0_Random; @@ -385,6 +424,7 @@ struct CPUMIPSState { #define CP0C2_SA 0 int32_t CP0_Config3; #define CP0C3_M31 +#define CP0C3_MSAP 28 #define CP0C3_BP 27 #define CP0C3_BI 26 #define CP0C3_ISA_ON_EXC 16 @@ -462,7 +502,7 @@ struct CPUMIPSState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags;/* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x5807FF +#define MIPS_HFLAG_TMASK 0x15807FF #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -508,6 +548,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_HWRENA_ULR 0x20 /* ULR bit from HWREna is set. */ #define MIPS_HFLAG_SBRI 0x40 /* R6 SDBBP causes RI excpt. in user mode */ #define MIPS_HFLAG_FBNSLOT 0x80 /* Forbidden slot */ +#define MIPS_HFLAG_MSA 0x100 target_ulong btarget;/* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -663,6 +704,8 @@ enum { EXCP_C2E, EXCP_CACHE, /* 32 */ EXCP_DSPDIS, +EXCP_MSADIS, +EXCP_MSAFPE, EXCP_TLBXI, EXCP_TLBRI, @@ -764,7 +807,7 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | - MIPS_HFLAG_SBRI); + MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -837,6 +880,11 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags |= MIPS_HFLAG_COP1X; } } +if (env->insn_flags & ASE_MSA) { +if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) { +env->hflags |= MIPS_HFLAG_MSA; +} +} } #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 6cb62b2..1784227 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -45,6 +45,7 @@ #define ASE_MT0x0020 #define ASE_SMARTMIPS 0x0040 #define ASE_MICROMIPS 0x0080 +#define ASE_MSA 0x0100 /* Chip specific instructions. */ #defineINSN_LOONGSON2E 0x2000 diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index c6de86e..0c75ec8 100644 --- a/target-mips/op_helper.c ++
[Qemu-devel] [PATCH v2 03/20] target-mips: remove duplicated mips/ieee mapping function
Signed-off-by: Yongbok Kim --- target-mips/cpu.h |4 target-mips/gdbstub.c |7 --- target-mips/op_helper.c |4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index fb5abda..6d3db79 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -760,6 +760,10 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, #endif target_ulong exception_resume_pc (CPUMIPSState *env); +/* op_helper.c */ +extern unsigned int ieee_rm[]; +int ieee_ex_to_mips(int xcpt); + static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c index 5b72d58..f65fec2 100644 --- a/target-mips/gdbstub.c +++ b/target-mips/gdbstub.c @@ -73,13 +73,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return 0; } -/* convert MIPS rounding mode in FCR31 to IEEE library */ -static unsigned int ieee_rm[] = { -float_round_nearest_even, -float_round_to_zero, -float_round_up, -float_round_down -}; #define RESTORE_ROUNDING_MODE \ set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \ &env->active_fpu.fp_status) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 0c75ec8..7cbf4cf 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2340,7 +2340,7 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, #define FP_TO_INT64_OVERFLOW 0x7fffULL /* convert MIPS rounding mode in FCR31 to IEEE library */ -static unsigned int ieee_rm[] = { +unsigned int ieee_rm[] = { float_round_nearest_even, float_round_to_zero, float_round_up, @@ -2461,7 +2461,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) do_raise_exception(env, EXCP_FPE, GETPC()); } -static inline int ieee_ex_to_mips(int xcpt) +int ieee_ex_to_mips(int xcpt) { int ret = 0; if (xcpt) { -- 1.7.4
[Qemu-devel] [PATCH v2 15/20] target-mips: add MSA 3RF format instructions
add MSA 3RF format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 42 ++ target-mips/msa_helper.c | 1497 ++ target-mips/translate.c | 162 + 3 files changed, 1701 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index f6fe5bf..fb9427e 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -858,3 +858,45 @@ DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_2(msa_cfcmsa, tl, env, i32) DEF_HELPER_3(msa_move_v, void, env, i32, i32) + +DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 22e05c0..03446cf 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -732,6 +732,29 @@ static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2) return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df); } +static inline int64_t msa_mul_q_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int64_t q_min = DF_MIN_INT(df); +int64_t q_max = DF_MAX_INT(df); + +if (arg1 == q_min && arg2 == q_min) { +return q_max; +} +return (arg1 * arg2) >> (DF_BITS(df) - 1); +} + +static inline int64_t msa_mulr_q_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int64_t q_min = DF_MIN_INT(df); +int64_t q_max = DF_MAX_INT(df); +int64_t r_bit = 1 << (DF_BITS(df) - 2); + +if (arg1 == q_min && arg2 == q_min) { +return q_max; +} +return (arg1 * arg2 + r_bit) >> (DF_BITS(df) - 1); +} + #define MSA_BINOP_DF(func) \ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ uint32_t wd, uint32_t ws, uint32_t wt) \ @@ -813,6 +836,9 @@ MSA_BINOP_DF(hadd_s) MSA_BINOP_DF(hadd_u) MSA_BINOP_DF(hsub_s) MSA_BINOP_DF(hsub_u) + +MSA_BINOP_DF(mul_q) +MSA_BINOP_DF(mulr_q) #undef MSA_BINOP_DF void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -868,6 +894,64 @@ static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1, return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); } +static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1, +int64_t arg2) +{ +int64_t q_prod, q_ret; + +int64_t q_max = DF_MAX_INT(df); +int64_t q_min = DF_MIN_INT(df); + +q_prod = arg1 * arg2; +q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod) >> (DF_BITS(df) - 1); + +return (q_ret <
[Qemu-devel] [PATCH v2 07/20] target-mips: add msa_reset(), global msa register
add msa_reset() and global msa register (d type only) Signed-off-by: Yongbok Kim --- target-mips/translate.c | 56 ++ target-mips/translate_init.c | 35 ++ 2 files changed, 91 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 555f89b..f1160aa 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1356,6 +1356,7 @@ static TCGv cpu_dspctrl, btarget, bcond; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; +static TCGv_i64 msa_wr_d[64]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; @@ -1454,6 +1455,25 @@ static const char * const fregnames[] = { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; +static const char * const msaregnames[] = { +"w0.d0", "w0.d1", "w1.d0", "w1.d1", +"w2.d0", "w2.d1", "w3.d0", "w3.d1", +"w4.d0", "w4.d1", "w5.d0", "w5.d1", +"w6.d0", "w6.d1", "w7.d0", "w7.d1", +"w8.d0", "w8.d1", "w9.d0", "w9.d1", +"w10.d0", "w10.d1", "w11.d0", "w11.d1", +"w12.d0", "w12.d1", "w13.d0", "w13.d1", +"w14.d0", "w14.d1", "w15.d0", "w15.d1", +"w16.d0", "w16.d1", "w17.d0", "w17.d1", +"w18.d0", "w18.d1", "w19.d0", "w19.d1", +"w20.d0", "w20.d1", "w21.d0", "w21.d1", +"w22.d0", "w22.d1", "w23.d0", "w23.d1", +"w24.d0", "w24.d1", "w25.d0", "w25.d1", +"w26.d0", "w26.d1", "w27.d0", "w27.d1", +"w28.d0", "w28.d1", "w29.d0", "w29.d1", +"w30.d0", "w30.d1", "w31.d0", "w31.d1", +}; + #define MIPS_DEBUG(fmt, ...) \ do { \ if (MIPS_DEBUG_DISAS) { \ @@ -17206,6 +17226,27 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) } } +/* MIPS SIMD Architecture (MSA) */ +static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx) +{ +if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && + !(ctx->hflags & MIPS_HFLAG_F64))) { +generate_exception(ctx, EXCP_RI); +return 0; +} + +if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { +if (ctx->insn_flags & ASE_MSA) { +generate_exception(ctx, EXCP_MSADIS); +return 0; +} else { +generate_exception(ctx, EXCP_RI); +return 0; +} +} +return 1; +} + static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -18136,6 +18177,15 @@ void mips_tcg_init(void) fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); } +for (i = 0; i < 32; i++) { +int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); +msa_wr_d[i * 2] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); +off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); +msa_wr_d[i * 2 + 1] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]); +} + cpu_PC = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.PC), "PC"); for (i = 0; i < MIPS_DSP_ACC; i++) { @@ -18243,6 +18293,7 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; +env->msair = env->cpu_model->MSAIR; env->insn_flags = env->cpu_model->insn_flags; #if defined(CONFIG_USER_ONLY) @@ -18340,6 +18391,11 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Status |= (1 << CP0St_FR); } +/* MSA */ +if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { +msa_reset(env); +} + compute_hflags(env); cs->exception_index = EXCP_NONE; } diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 0b70d05..8fb8bf8 100644 --- a/target-mips/translate_init.c +++ b/target-mip
[Qemu-devel] [PATCH v2 09/20] target-mips: add MSA branch instructions
add MSA branch instructions Signed-off-by: Yongbok Kim --- target-mips/translate.c | 333 +++ 1 files changed, 219 insertions(+), 114 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index f1160aa..0df86cc 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17247,6 +17247,92 @@ static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx) return 1; } +static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt) +{ +/* generates tcg ops to check if any element is 0 */ +/* Note this function only works with MSA_WRLEN = 128 */ +uint64_t eval_zero_or_big = 0; +uint64_t eval_big = 0; +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +switch (df) { +case DF_BYTE: +eval_zero_or_big = 0x0101010101010101ULL; +eval_big = 0x8080808080808080ULL; +break; +case DF_HALF: +eval_zero_or_big = 0x0001000100010001ULL; +eval_big = 0x8000800080008000ULL; +break; +case DF_WORD: +eval_zero_or_big = 0x00010001ULL; +eval_big = 0x80008000ULL; +break; +case DF_DOUBLE: +eval_zero_or_big = 0x0001ULL; +eval_big = 0x8000ULL; +break; +} +tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big); +tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]); +tcg_gen_andi_i64(t0, t0, eval_big); +tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big); +tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]); +tcg_gen_andi_i64(t1, t1, eval_big); +tcg_gen_or_i64(t0, t0, t1); +/* if all bits are zero then all elements are not zero */ +/* if some bit is non-zero then some element is zero */ +tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(tresult, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} + +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) +{ +uint8_t df = (ctx->opcode >> 21) & 0x3; +uint8_t wt = (ctx->opcode >> 16) & 0x1f; +int64_t s16 = (int16_t)ctx->opcode; + +check_msa_access(env, ctx); + +if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { +MIPS_DEBUG("CTI in delay / forbidden slot"); +generate_exception(ctx, EXCP_RI); +return; +} +switch (op1) { +case OPC_BZ_V: +case OPC_BNZ_V: +{ +TCGv_i64 t0 = tcg_temp_new_i64(); +tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]); +tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ? +TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(bcond, t0); +tcg_temp_free_i64(t0); +} +break; +case OPC_BZ_B: +case OPC_BZ_H: +case OPC_BZ_W: +case OPC_BZ_D: +gen_check_zero_element(bcond, df, wt); +break; +case OPC_BNZ_B: +case OPC_BNZ_H: +case OPC_BNZ_W: +case OPC_BNZ_D: +gen_check_zero_element(bcond, df, wt); +tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); +break; +} + +ctx->btarget = ctx->pc + (s16 << 2) + 4; + +ctx->hflags |= MIPS_HFLAG_BC; +ctx->hflags |= MIPS_HFLAG_BDS32; +} static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -17568,133 +17654,152 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_CP1: -if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { +op1 = MASK_CP1(ctx->opcode); + +switch (op1) { +case OPC_MFHC1: +case OPC_MTHC1: check_cp1_enabled(ctx); -op1 = MASK_CP1(ctx->opcode); -switch (op1) { -case OPC_MFHC1: -case OPC_MTHC1: -check_insn(ctx, ISA_MIPS32R2); -case OPC_MFC1: -case OPC_CFC1: -case OPC_MTC1: -case OPC_CTC1: -gen_cp1(ctx, op1, rt, rd); -break; +check_insn(ctx, ISA_MIPS32R2); +case OPC_MFC1: +case OPC_CFC1: +case OPC_MTC1: +case OPC_CTC1: +check_cp1_enabled(ctx); +gen_cp1(ctx, op1, rt, rd); +break; #if defined(TARGET_MIPS64) -case OPC_DMFC1: -case OPC_DMTC1: -check_insn(ctx, ISA_MIPS3); -gen_cp1(ctx, op1, rt, rd); -break; +case OPC_DMFC1: +case OPC_DMTC1: +check_cp1_enabled(ctx); +check_insn(ctx, ISA_MIPS3); +gen_cp1(ctx, op1, rt, rd); +break; #endif -case OPC_BC1EQZ: /* OPC_BC1ANY2 */ -if (ctx->insn_flags & ISA_MIPS32R6) { -
[Qemu-devel] [PATCH v2 05/20] target-mips: stop translation after ctc1
stop translation as ctc1 instruction can change hflags Signed-off-by: Yongbok Kim --- target-mips/translate.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 9a8f5c9..b388ba5 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7490,12 +7490,15 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(rd); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; break; /* COP2: Not implemented. */ case 4: @@ -8089,12 +8092,15 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(fs); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; opn = "ctc1"; break; #if defined(TARGET_MIPS64) -- 1.7.4
[Qemu-devel] [PATCH v2 19/20] disas/mips.c: disassemble MSA instructions
disassemble MIPS SIMD Architecture instructions Signed-off-by: Yongbok Kim --- disas/mips.c | 716 +- 1 files changed, 714 insertions(+), 2 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index 4974bc0..2614c52 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -220,6 +220,28 @@ see <http://www.gnu.org/licenses/>. */ #define OP_SH_MTACC_D 13 #define OP_MASK_MTACC_D0x3 +/* MSA */ +#define OP_MASK_1BIT0x1 +#define OP_SH_1BIT 16 +#define OP_MASK_2BIT0x3 +#define OP_SH_2BIT 16 +#define OP_MASK_3BIT0x7 +#define OP_SH_3BIT 16 +#define OP_MASK_4BIT0xf +#define OP_SH_4BIT 16 +#define OP_MASK_5BIT0x1f +#define OP_SH_5BIT 16 +#define OP_MASK_10BIT 0x3ff +#define OP_SH_10BIT 11 +#define OP_MASK_MSACR11 0x1f +#define OP_SH_MSACR11 11 +#define OP_MASK_MSACR6 0x1f +#define OP_SH_MSACR66 +#define OP_MASK_GPR 0x1f +#define OP_SH_GPR 6 +#define OP_MASK_1_TO_4 0x3 +#define OP_SH_1_TO_46 + #defineOP_OP_COP0 0x10 #defineOP_OP_COP1 0x11 #defineOP_OP_COP2 0x12 @@ -510,6 +532,9 @@ struct mips_opcode /* Instruction writes MDMX accumulator. */ #define INSN2_WRITE_MDMX_ACC 0x0004 +/* Reads the general purpose register in OP_*_RD. */ +#define INSN2_READ_GPR_D0x0200 + /* Instruction is actually a macro. It should be ignored by the disassembler, and requires special treatment by the assembler. */ #define INSN_MACRO 0x @@ -567,7 +592,12 @@ struct mips_opcode #define INSN_55000x0200 /* MDMX ASE */ -#define INSN_MDMX 0x0400 +#define INSN_MDMX 0x/* Deprecated */ + +/* MIPS MSA Extension */ +#define INSN_MSA 0x0400 +#define INSN_MSA640x0400 + /* MT ASE */ #define INSN_MT 0x0800 /* SmartMIPS ASE */ @@ -1204,6 +1234,17 @@ extern const int bfd_mips16_num_opcodes; /* MIPS MT ASE support. */ #define MT32 INSN_MT +/* MSA */ +#define MSA INSN_MSA +#define MSA64 INSN_MSA64 +#define WR_VD INSN_WRITE_FPR_D/* Reuse INSN_WRITE_FPR_D */ +#define RD_VD WR_VD /* Reuse WR_VD */ +#define RD_VT INSN_READ_FPR_T /* Reuse INSN_READ_FPR_T */ +#define RD_VS INSN_READ_FPR_S /* Reuse INSN_READ_FPR_S */ +#define RD_dINSN2_READ_GPR_D/* Reuse INSN2_READ_GPR_D */ + +#define RD_rd6 0 + /* The order of overloaded instructions matters. Label arguments and register arguments look the same. Instructions that can have either for arguments must apear in the correct order in this table for the @@ -1363,6 +1404,541 @@ const struct mips_opcode mips_builtin_opcodes[] = {"cmp.sor.d", "D,S,T", 0x46a00019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, {"cmp.sune.d", "D,S,T", 0x46a0001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, {"cmp.sne.d", "D,S,T", 0x46a0001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, + +/* MSA */ +{"sll.b", "+d,+e,+f", 0x780d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.h", "+d,+e,+f", 0x782d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.w", "+d,+e,+f", 0x784d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.d", "+d,+e,+f", 0x786d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"slli.b", "+d,+e,+7", 0x7879, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"slli.h", "+d,+e,+8", 0x7869, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"slli.w", "+d,+e,+9", 0x7849, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"slli.d", "+d,+e,'", 0x7809, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"sra.b", "+d,+e,+f", 0x788d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.h", "+d,+e,+f", 0x78ad, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.w", "+d,+e,+f", 0x78cd, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.d", "+d,+e,+f", 0x78ed, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"srai.b", "+d,+e,+7", 0x78f9, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"srai.h", "+d,+e,+8", 0x78e9, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"srai.w", "+d,+e,+9", 0x78c9, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"srai.d", "+d,+e,'", 0x7889, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"srl.b", "+d,+e,+f", 0x790d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MS
[Qemu-devel] [PATCH v2 13/20] target-mips: add MSA 3R format instructions
add MSA 3R format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 64 + target-mips/msa_helper.c | 628 ++ target-mips/translate.c | 244 ++ 3 files changed, 936 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index b5f171c..4759c24 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -784,3 +784,67 @@ DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index da43439..b4a6a35 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -453,3 +453,631 @@ MSA_TEROP_IMMU_DF(binsli, binsl) MSA_TEROP_IMMU_DF(binsri, binsr) #undef MSA_TEROP_IMMU_DF +static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1; +uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2; +return abs_arg1 > abs_arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int
[Qemu-devel] [PATCH v2 08/20] target-mips: add msa_helper.c
add msa_helper.c Signed-off-by: Yongbok Kim --- target-mips/Makefile.objs |2 +- target-mips/msa_helper.c | 49 + 2 files changed, 50 insertions(+), 1 deletions(-) create mode 100644 target-mips/msa_helper.c diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 716244f..108fd9b 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,4 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o -obj-y += gdbstub.o +obj-y += gdbstub.o msa_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c new file mode 100644 index 000..b65fb27 --- /dev/null +++ b/target-mips/msa_helper.c @@ -0,0 +1,49 @@ +/* + * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU. + * + * Copyright (c) 2014 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "cpu.h" +#include "exec/helper-proto.h" + +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +#define DF_MAX_INT(df) (int64_t)((1LL << (DF_BITS(df) - 1)) - 1) +#define M_MAX_INT(m)(int64_t)((1LL << ((m) - 1)) - 1) + +#define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1))) +#define M_MIN_INT(m)(int64_t)(-(1LL << ((m) - 1))) + +#define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df))) +#define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m))) + +#define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df)) +#define SIGNED(x, df) \ +int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df))) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +static inline void msa_move_v(wr_t *pwd, wr_t *pws) +{ +uint32_t i; + +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { +pwd->d[i] = pws->d[i]; +} +} -- 1.7.4
[Qemu-devel] [PATCH v2 10/20] target-mips: add MSA I8 format instructions
add MSA I8 format instructions Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/helper.h | 10 + target-mips/msa_helper.c | 67 +++ target-mips/translate.c | 86 - 3 files changed, 161 insertions(+), 2 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index aea12a9..ec1c0e5 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -748,3 +748,13 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) #endif DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) + +/* MIPS SIMD Architecture */ +DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index b65fb27..46ffaa5 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -47,3 +47,70 @@ static inline void msa_move_v(wr_t *pwd, wr_t *pws) pwd->d[i] = pws->d[i]; } } + +#define MSA_FN_IMM8(FUNC, DEST, OPERATION) \ +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ +uint32_t i8)\ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +uint32_t i; \ +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ +DEST = OPERATION; \ +} \ +} + +MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8) +MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8) +MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8)) +MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8) + +#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ +UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) +MSA_FN_IMM8(bmnzi_b, pwd->b[i], \ +BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ +UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) +MSA_FN_IMM8(bmzi_b, pwd->b[i], \ +BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_SELECT(dest, arg1, arg2, df) \ +UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) +MSA_FN_IMM8(bseli_b, pwd->b[i], \ +BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#undef MSA_FN_IMM8 + +#define SHF_POS(i, imm) ((i & 0xfc) + ((imm >> (2 * (i & 0x03))) & 0x03)) + +void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t imm) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +wr_t wx, *pwx = &wx; +uint32_t i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwx->b[i] = pws->b[SHF_POS(i, imm)]; +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwx->h[i] = pws->h[SHF_POS(i, imm)]; +} +break; +case DF_WORD: +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { +pwx->w[i] = pws->w[SHF_POS(i, imm)]; +} +break; +default: +assert(0); +} +msa_move_v(pwd, pwx); +} + diff --git a/target-mips/translate.c b/target-mips/translate.c index 0df86cc..b2934d7 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17333,6 +17333,88 @@ static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) ctx->hflags |= MIPS_HFLAG_BC; ctx->hflags |= MIPS_HFLAG_BDS32; } + +static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I8(op)(MASK_MSA_MINOR(op) | (op & (0x03 << 24))) + +uint32_t opcode = ctx->opcode; + +uint8_t i8 = (opcode >> 16) & 0xff; +uint8_t ws = (opcode >> 11) & 0x1f; +uint8_t wd = (opcode >> 6) & 0x1f; + +TCGv_i32 twd = tcg_const_i32(wd); +TCGv_i32 tws = tcg_const_i32(ws); +TCGv_i32 ti8 = tcg_const_i32(i8); + +switch (MASK_MSA_I8(opcode)) { +case OPC_ANDI_B: +gen_helper_msa_andi_b(cpu_env, twd, tws, ti8); +break; +case OPC_ORI_B: +gen_helper_msa_or
[Qemu-devel] [PATCH v2 16/20] target-mips: add MSA VEC/2R format instructions
add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 12 target-mips/msa_helper.c | 140 ++ target-mips/translate.c | 113 + 3 files changed, 265 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index fb9427e..53dc040 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -900,3 +900,15 @@ DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 03446cf..2319fca 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -114,6 +114,34 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } +#define MSA_FN_VECTOR(FUNC, DEST, OPERATION)\ +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ +uint32_t wt)\ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ +uint32_t i; \ +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ +DEST = OPERATION; \ +} \ +} + +MSA_FN_VECTOR(and_v, pwd->d[i], pws->d[i] & pwt->d[i]) +MSA_FN_VECTOR(or_v, pwd->d[i], pws->d[i] | pwt->d[i]) +MSA_FN_VECTOR(nor_v, pwd->d[i], ~(pws->d[i] | pwt->d[i])) +MSA_FN_VECTOR(xor_v, pwd->d[i], pws->d[i] ^ pwt->d[i]) +MSA_FN_VECTOR(bmnz_v, pwd->d[i], \ +BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +MSA_FN_VECTOR(bmz_v, pwd->d[i], \ +BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +MSA_FN_VECTOR(bsel_v, pwd->d[i], \ +BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +#undef BIT_MOVE_IF_NOT_ZERO +#undef BIT_MOVE_IF_ZERO +#undef BIT_SELECT +#undef MSA_FN_VECTOR + static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) { return arg1 + arg2; @@ -1332,6 +1360,118 @@ void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) msa_move_v(pwd, pws); } +static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg) +{ +uint64_t x; + +x = UNSIGNED(arg, df); + +x = (x & 0xULL) + ((x >> 1) & 0xULL); +x = (x & 0xULL) + ((x >> 2) & 0xULL); +x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >> 4) & 0x0F0F0F0F0F0F0F0FULL); +x = (x & 0x00FF00FF00FF00FFULL) + ((x >> 8) & 0x00FF00FF00FF00FFULL); +x = (x & 0xULL) + ((x >> 16) & 0xULL); +x = (x & 0xULL) + ((x >> 32)); + +return x; +} + +static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg) +{ +uint64_t x, y; +int n, c; + +x = UNSIGNED(arg, df); +n = DF_BITS(df); +c = DF_BITS(df) / 2; + +do { +y = x >> c; +if (y != 0) { +n = n - c; +x = y; +} +c = c >> 1; +} while (c != 0); + +return n - x; +} + +static inline int64_t msa_nloc_df(uint32_t df, int64_t arg) +{ +return msa_nlzc_df(df, UNSIGNED((~arg), df)); +} + +void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t rs) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +uint32_t i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwd->b[i] = (int8_t)env->active_tc.gpr[rs]; +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwd->h[i] = (int16_t)env->active
[Qemu-devel] [PATCH v2 11/20] target-mips: add MSA I5 format instruction
add MSA I5 format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 13 target-mips/msa_helper.c | 142 ++ target-mips/translate.c | 79 + 3 files changed, 234 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index ec1c0e5..585eaa9 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -758,3 +758,16 @@ DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) + +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 46ffaa5..ffdde07 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -114,3 +114,145 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } +static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 + arg2; +} + +static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 - arg2; +} + +static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 == arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 <= arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 <= u_arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 < arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 < u_arg2 ? -1 : 0; +} + +static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 > arg2 ? arg1 : arg2; +} + +static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 > u_arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 < arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 < u_arg2 ? arg1 : arg2; +} + +#define MSA_BINOP_IMM_DF(helper, func) \ +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ +uint32_t wd, uint32_t ws, int64_t u5) \ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +uint32_t i; \ +\ +switch (df) { \ +case DF_BYTE: \ +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ +pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \ +} \ +break; \ +case DF_HALF: \ +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {\ +pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \ +} \ +break; \ +case DF_WORD: \ +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {\ +
[Qemu-devel] [PATCH v2 14/20] target-mips: add MSA ELM format instructions
add MSA ELM format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 10 +++ target-mips/msa_helper.c | 162 ++ target-mips/translate.c | 118 + 3 files changed, 290 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 4759c24..f6fe5bf 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -848,3 +848,13 @@ DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) +DEF_HELPER_2(msa_cfcmsa, tl, env, i32) +DEF_HELPER_3(msa_move_v, void, env, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index b4a6a35..22e05c0 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1081,3 +1081,165 @@ MSA_FN_DF(vshf_df) #undef MSA_DO #undef MSA_LOOP_COND #undef MSA_FN_DF + +void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +msa_sld_df(env, df, pwd, pws, n); +} + +void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +msa_splat_df(env, df, pwd, pws, n); +} + +void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, + uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df); + +switch (df) { +case DF_BYTE: +env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: +env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: +env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: +env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; +break; +#endif +default: +assert(0); +} +} + +void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, + uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df); + +switch (df) { +case DF_BYTE: +env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: +env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: +env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: +env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n]; +break; +#endif +default: +assert(0); +} +} + +void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +target_ulong rs = env->active_tc.gpr[rs_num]; + +switch (df) { +case DF_BYTE: +pwd->b[n] = (int8_t)rs; +break; +case DF_HALF: +pwd->h[n] = (int16_t)rs; +break; +case DF_WORD: +pwd->w[n] = (int32_t)rs; +break; +case DF_DOUBLE: +pwd->d[n] = (int64_t)rs; +break; +default: +assert(0); +} +} + +void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +switch (df) { +case DF_BYTE: +pwd->b[n] = (int8_t)pws->b[0]; +break; +case DF_HALF: +pwd->h[n] = (int16_t)pws->h[0]; +break; +case DF_WORD: +pwd->w[n] = (int32_t)pws->w[0]; +break; +case DF_DOUBLE: +pwd->d[n] = (int64_t)pws->d[0]; +break; +default: +assert(0); +} +} + +void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd) +{ +switch (cd) { +case 0: +break; +case 1: +env->active_tc.msacsr = (int32_t)elm & MSACSR_MASK; +/* set float_status rounding mode */ +set_float_rounding_mode( +ieee_r
[Qemu-devel] [PATCH v2 17/20] target-mips: add MSA 2RF format instructions
add MSA 2RF format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 17 ++ target-mips/msa_helper.c | 579 ++ target-mips/translate.c | 76 ++ 3 files changed, 672 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 53dc040..19ea0b5 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -912,3 +912,20 @@ DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 2319fca..02ee50a 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1472,6 +1472,74 @@ MSA_UNOP_DF(nlzc) MSA_UNOP_DF(nloc) MSA_UNOP_DF(pcnt) +#define MSA_FLOAT_CLASS_SIGNALING_NAN 0x001 +#define MSA_FLOAT_CLASS_QUIET_NAN 0x002 + +#define MSA_FLOAT_CLASS_NEGATIVE_INFINITY 0x004 +#define MSA_FLOAT_CLASS_NEGATIVE_NORMAL0x008 +#define MSA_FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 +#define MSA_FLOAT_CLASS_NEGATIVE_ZERO 0x020 + +#define MSA_FLOAT_CLASS_POSITIVE_INFINITY 0x040 +#define MSA_FLOAT_CLASS_POSITIVE_NORMAL0x080 +#define MSA_FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 +#define MSA_FLOAT_CLASS_POSITIVE_ZERO 0x200 + +#define MSA_FLOAT_CLASS(ARG, BITS) \ +do {\ +int mask; \ +int snan, qnan, inf, neg, zero, dnmz; \ +\ +snan = float ## BITS ## _is_signaling_nan(ARG); \ +qnan = float ## BITS ## _is_quiet_nan(ARG); \ +inf = float ## BITS ## _is_infinity(ARG); \ +neg = float ## BITS ## _is_neg(ARG); \ +zero = float ## BITS ## _is_zero(ARG); \ +dnmz = float ## BITS ## _is_zero_or_denormal(ARG); \ +\ +mask = 0; \ +if (snan) { \ +mask |= MSA_FLOAT_CLASS_SIGNALING_NAN; \ +} \ +else if (qnan) {\ +mask |= MSA_FLOAT_CLASS_QUIET_NAN; \ +} else if (neg) { \ +if (inf) { \ +mask |= MSA_FLOAT_CLASS_NEGATIVE_INFINITY; \ +} else if (zero) { \ +mask |= MSA_FLOAT_CLASS_NEGATIVE_ZERO; \ +} else if (dnmz) { \ +mask |= MSA_FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ +} \ +else { \ +mask |= MSA_FLOAT_CLASS_NEGATIVE_NORMAL;\ +} \ +} else {\ +if (inf) { \ +mask |= MSA_FLOAT_CLASS_POSITIVE_INFINITY; \ +} else if (zero) { \ +mask |= MSA_FLOAT_CLASS_POSITIVE_ZERO; \ +} else if (dnmz) { \ +mask |= MSA_FLOAT_CLASS_POSITIVE_SUBNORMAL; \ +} else {\ +mask |= MSA_FLOAT_CLASS_POSITIVE_NORMAL;\ +} \ +} \ +return mask
[Qemu-devel] [PATCH v2 18/20] target-mips: add MSA MI10 format instructions
add MSA MI10 format instructions update LSA and DLSA for MSA Signed-off-by: Yongbok Kim --- target-mips/helper.h|3 ++ target-mips/op_helper.c | 77 +++ target-mips/translate.c | 50 ++- 3 files changed, 129 insertions(+), 1 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 19ea0b5..ca97f9a 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -929,3 +929,6 @@ DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) + +DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s64) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e878442..6d23b98 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -3625,3 +3625,80 @@ FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) + +/* MSA */ +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, + int64_t s10) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); + int i; + + switch (df) { + case DF_BYTE: + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { + pwd->b[i] = do_lbu(env, addr + (i << DF_BYTE), + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_HALF: + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { + pwd->h[i] = do_lhu(env, addr + (i << DF_HALF), + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + pwd->w[i] = do_lw(env, addr + (i << DF_WORD), + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + pwd->d[i] = do_ld(env, addr + (i << DF_DOUBLE), + env->hflags & MIPS_HFLAG_KSU); + } + break; + } +} + +void helper_msa_st_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, + int64_t s10) +{ + wr_t *pwd = &(env->active_fpu.fpr[wd].wr); + target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); + int i; + + switch (df) { + case DF_BYTE: + for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { + do_sb(env, addr + (i << DF_BYTE), pwd->b[i], + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_HALF: + for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { + do_sh(env, addr + (i << DF_HALF), pwd->h[i], + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_WORD: + for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { + do_sw(env, addr + (i << DF_WORD), pwd->w[i], + env->hflags & MIPS_HFLAG_KSU); + } + break; + case DF_DOUBLE: + for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { + do_sd(env, addr + (i << DF_DOUBLE), pwd->d[i], + env->hflags & MIPS_HFLAG_KSU); + } + break; + } +} diff --git a/target-mips/translate.c b/target-mips/translate.c index 4f55d84..da5f48c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -16319,7 +16319,8 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_trap(ctx, op1, rs, rt, -1); break; case OPC_LSA: /* OPC_PMON */ -if (ctx->insn_flags & ISA_MIPS32R6) { +if ((ctx->insn_flags & ISA_MIPS32R6) || +(env->CP0_Config3 & (1 << CP0C3_MSAP)) ) { decode_opc_special_r6(env, ctx); } else { /* Pmon entry point, also R4010 selsl */ @@ -16417,6 +16418,12 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) break; } break; +case OPC_DLSA: +if ((ctx->insn_flags & ISA_MIPS32R6) || +(env->CP0_Config3 & (1 << CP0C3_MSAP)) ) { +decode_opc_special_r6(env, ctx); +} +break; #endif default: if (ctx->insn_flags & ISA_MIPS32R6) { @@ -18284,6 +18291,47 @@ static
[Qemu-devel] [PATCH v2 20/20] target-mips: add MSA support to mips32r5-generic
add MSA support to mips32r5-generic core definition Signed-off-by: Yongbok Kim --- target-mips/translate_init.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 8fb8bf8..0b4b597 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -358,7 +358,7 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M), +.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M), .CP0_Config4_rw_bitmask = 0, .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), @@ -376,7 +376,7 @@ static const mips_def_t mips_defs[] = (0x93 << FCR0_PRID), .SEGBITS = 32, .PABITS = 32, -.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, +.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2 | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, #if defined(TARGET_MIPS64) -- 1.7.4
Re: [Qemu-devel] [PATCH v3 13/15] target-mips: add restrictions for possible values in registers
mp; ISA_MIPS32R6) || (arg1 & 0xff00)) { return; +} env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017f) | ((arg1 & 0xfe) << 24) | ((arg1 & 0x1) << 23); break; @@ -2408,9 +2440,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) ((arg1 & 0x4) << 22); break; case 31: -if (arg1 & 0x007c) -return; -env->active_fpu.fcr31 = arg1; +if (env->insn_flags & ISA_MIPS32R6) { +uint32_t mask = 0xfefc; +env->active_fpu.fcr31 = (arg1 & ~mask) | +(env->active_fpu.fcr31 & mask); +} else if (!(arg1 & 0x007c)) { +env->active_fpu.fcr31 = arg1; +} break; default: return; Reviewed-by: Yongbok Kim Regards, Yongbok
Re: [Qemu-devel] [PATCH v3 08/15] target-mips: add BadInstr and BadInstrP support
+default: +goto die; +} break; case 9: switch (sel) { @@ -6054,6 +6086,22 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); rn = "BadVAddr"; break; +case 1: +if (ctx->bi) { +gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr)); +rn = "BadInstr"; +} else { +gen_mfc0_unimplemented(ctx, arg); +} +break; +case 2: +if (ctx->bp) { +gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP)); +rn = "BadInstrP"; +} else { +gen_mfc0_unimplemented(ctx, arg); +} +break; default: goto die; } @@ -6639,8 +6687,22 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) } break; case 8: -/* ignored */ -rn = "BadVAddr"; +switch (sel) { +case 0: +/* ignored */ +rn = "BadVAddr"; +break; +case 1: +/* ignored */ +rn = "BadInstr"; +break; +case 2: +/* ignored */ +rn = "BadInstrP"; +break; +default: +goto die; +} break; case 9: switch (sel) { @@ -16862,7 +16924,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) /* make sure instructions are on a word boundary */ if (ctx->pc & 0x3) { env->CP0_BadVAddr = ctx->pc; -generate_exception(ctx, EXCP_AdEL); +generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL); return; } @@ -17500,6 +17562,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3; +ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1; +ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1; /* Restore delay slot state from the tb context. */ ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI); otherwise, Reviewed-by: Yongbok Kim Regards, Yongbok
Re: [Qemu-devel] [PATCH v3 09/15] target-mips: update cpu_save/cpu_load to support new registers
On 24/10/2014 13:42, Leon Alrae wrote: Signed-off-by: Leon Alrae --- target-mips/cpu.h | 2 +- target-mips/machine.c | 26 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 4687f4f..c66a725 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -558,7 +558,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env); extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env); -#define CPU_SAVE_VERSION 4 +#define CPU_SAVE_VERSION 5 /* MMU modes definitions. We carefully match the indices with our hflags layout. */ diff --git a/target-mips/machine.c b/target-mips/machine.c index 0496faa..0ba7d73 100644 --- a/target-mips/machine.c +++ b/target-mips/machine.c @@ -61,7 +61,12 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be32s(f, &env->tlb->nb_tlb); qemu_put_be32s(f, &env->tlb->tlb_in_use); for(i = 0; i < MIPS_TLB_MAX; i++) { -uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) | +uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].EHINV << 15) | + (env->tlb->mmu.r4k.tlb[i].RI1 << 14) | + (env->tlb->mmu.r4k.tlb[i].RI0 << 13) | + (env->tlb->mmu.r4k.tlb[i].XI1 << 12) | + (env->tlb->mmu.r4k.tlb[i].XI0 << 11) | + (env->tlb->mmu.r4k.tlb[i].G << 10) | (env->tlb->mmu.r4k.tlb[i].C0 << 7) | (env->tlb->mmu.r4k.tlb[i].C1 << 4) | (env->tlb->mmu.r4k.tlb[i].V0 << 3) | @@ -111,6 +116,8 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_sbe32s(f, &env->CP0_SRSConf4); qemu_put_sbe32s(f, &env->CP0_HWREna); qemu_put_betls(f, &env->CP0_BadVAddr); +qemu_put_be32s(f, &env->CP0_BadInstr); +qemu_put_be32s(f, &env->CP0_BadInstrP); qemu_put_sbe32s(f, &env->CP0_Count); qemu_put_betls(f, &env->CP0_EntryHi); qemu_put_sbe32s(f, &env->CP0_Compare); @@ -144,6 +151,9 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_sbe32s(f, &env->CP0_DataHi); qemu_put_betls(f, &env->CP0_ErrorEPC); qemu_put_sbe32s(f, &env->CP0_DESAVE); +for (i = 0; i < MIPS_KSCRATCH_NUM; i++) { +qemu_put_betls(f, &env->CP0_KScratch[i]); +} /* Save inactive TC state */ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) @@ -232,6 +242,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) env->tlb->mmu.r4k.tlb[i].V1 = (flags >> 2) & 1; env->tlb->mmu.r4k.tlb[i].D0 = (flags >> 1) & 1; env->tlb->mmu.r4k.tlb[i].D1 = (flags >> 0) & 1; +if (version_id >= 5) { +env->tlb->mmu.r4k.tlb[i].EHINV = (flags >> 15) & 1; +env->tlb->mmu.r4k.tlb[i].RI1 = (flags >> 14) & 1; +env->tlb->mmu.r4k.tlb[i].RI0 = (flags >> 13) & 1; +env->tlb->mmu.r4k.tlb[i].XI1 = (flags >> 12) & 1; +env->tlb->mmu.r4k.tlb[i].XI0 = (flags >> 11) & 1; +} qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]); qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]); } @@ -301,6 +318,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_sbe32s(f, &env->CP0_DataHi); qemu_get_betls(f, &env->CP0_ErrorEPC); qemu_get_sbe32s(f, &env->CP0_DESAVE); +if (version_id >= 5) { +qemu_get_be32s(f, &env->CP0_BadInstr); +qemu_get_be32s(f, &env->CP0_BadInstrP); +for (i = 0; i < MIPS_KSCRATCH_NUM; i++) { +qemu_get_betls(f, &env->CP0_KScratch[i]); +} +} /* Load inactive TC state */ for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) { Reviewed-by: Yongbok Kim Regards, Yongbok
[Qemu-devel] [PATCH v3 00/19] target-mips: add MSA module
For 2.2 Release. The following patchset implements MIPS SIMD Architecture module. MSA adds new instructions to MIPS Architecture that allow efficient parallel processing of vector operations. For more information refer to: MIPS Architecture Reference Manual Volume IV-j: The MIPS32 SIMD Architecture Module The document (MD00867) is available at: http://www.imgtec.com/mips/architectures/simd.asp The MSA floating-point is compliant with the IEEE Standard for Floating-Point Arithmetic 754TM-2008. However this patchset is not set up with the IEEE-2008 option as QEMU softfloat for MIPS has not been updated yet. v3: * fixes for mixed declarations and code * remove duplicated code * change data format for immediate values v2: * fixes for Leon's and James' comments * rebased top of R6 patchset * Code refactored mainly for msa_helper.c Yongbok Kim (19): target-mips: add MSA defines and data structure target-mips: add MSA exceptions target-mips: remove duplicated mips/ieee mapping function target-mips: stop translation after ctc1 target-mips: add MSA opcode enum target-mips: add msa_reset(), global msa register target-mips: add msa_helper.c target-mips: add MSA branch instructions target-mips: add MSA I8 format instructions target-mips: add MSA I5 format instruction target-mips: add MSA BIT format instructions target-mips: add MSA 3R format instructions target-mips: add MSA ELM format instructions target-mips: add MSA 3RF format instructions target-mips: add MSA VEC/2R format instructions target-mips: add MSA 2RF format instructions target-mips: add MSA MI10 format instructions disas/mips.c: disassemble MSA instructions target-mips: add MSA support to mips32r5-generic disas/mips.c | 716 +- target-mips/Makefile.objs|2 +- target-mips/cpu.h| 56 +- target-mips/gdbstub.c|7 - target-mips/helper.c | 10 + target-mips/helper.h | 185 +++ target-mips/mips-defs.h |1 + target-mips/msa_helper.c | 3437 ++ target-mips/op_helper.c | 89 +- target-mips/translate.c | 1647 +++-- target-mips/translate_init.c | 39 +- 11 files changed, 6052 insertions(+), 137 deletions(-) create mode 100644 target-mips/msa_helper.c -- 1.7.4
[Qemu-devel] [PATCH v3 03/19] target-mips: remove duplicated mips/ieee mapping function
Remove the duplicated ieee_rm in gdbstub.c. Make the other ieee_rm and ieee_ex_to_mips available to other files. Reviewed-by: James Hogan Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- target-mips/cpu.h |4 target-mips/gdbstub.c |7 --- target-mips/op_helper.c |4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index d08bbe7..d21da8e 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -760,6 +760,10 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, #endif target_ulong exception_resume_pc (CPUMIPSState *env); +/* op_helper.c */ +extern unsigned int ieee_rm[]; +int ieee_ex_to_mips(int xcpt); + static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c index 5b72d58..f65fec2 100644 --- a/target-mips/gdbstub.c +++ b/target-mips/gdbstub.c @@ -73,13 +73,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return 0; } -/* convert MIPS rounding mode in FCR31 to IEEE library */ -static unsigned int ieee_rm[] = { -float_round_nearest_even, -float_round_to_zero, -float_round_up, -float_round_down -}; #define RESTORE_ROUNDING_MODE \ set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \ &env->active_fpu.fp_status) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 0c75ec8..7cbf4cf 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2340,7 +2340,7 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, #define FP_TO_INT64_OVERFLOW 0x7fffULL /* convert MIPS rounding mode in FCR31 to IEEE library */ -static unsigned int ieee_rm[] = { +unsigned int ieee_rm[] = { float_round_nearest_even, float_round_to_zero, float_round_up, @@ -2461,7 +2461,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) do_raise_exception(env, EXCP_FPE, GETPC()); } -static inline int ieee_ex_to_mips(int xcpt) +int ieee_ex_to_mips(int xcpt) { int ret = 0; if (xcpt) { -- 1.7.4
[Qemu-devel] [PATCH v3 02/19] target-mips: add MSA exceptions
add MSA exceptions Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/helper.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index c92b25c..3a93c20 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -426,6 +426,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_CACHE] = "cache error", [EXCP_TLBXI] = "TLB execute-inhibit", [EXCP_TLBRI] = "TLB read-inhibit", +[EXCP_MSADIS] = "MSA disabled", +[EXCP_MSAFPE] = "MSA floating point", }; target_ulong exception_resume_pc (CPUMIPSState *env) @@ -667,6 +669,10 @@ void mips_cpu_do_interrupt(CPUState *cs) cause = 13; update_badinstr = 1; goto set_EPC; +case EXCP_MSAFPE: +cause = 14; +update_badinstr = 1; +goto set_EPC; case EXCP_FPE: cause = 15; update_badinstr = 1; @@ -681,6 +687,10 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_TLBXI: cause = 20; goto set_EPC; +case EXCP_MSADIS: +cause = 21; +update_badinstr = 1; +goto set_EPC; case EXCP_MDMX: cause = 22; goto set_EPC; -- 1.7.4
[Qemu-devel] [PATCH v3 07/19] target-mips: add msa_helper.c
add msa_helper.c Reviewed-by: James Hogan Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- target-mips/Makefile.objs |2 +- target-mips/msa_helper.c | 49 + 2 files changed, 50 insertions(+), 1 deletions(-) create mode 100644 target-mips/msa_helper.c diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 716244f..108fd9b 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,4 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o -obj-y += gdbstub.o +obj-y += gdbstub.o msa_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c new file mode 100644 index 000..b65fb27 --- /dev/null +++ b/target-mips/msa_helper.c @@ -0,0 +1,49 @@ +/* + * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU. + * + * Copyright (c) 2014 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "cpu.h" +#include "exec/helper-proto.h" + +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +#define DF_MAX_INT(df) (int64_t)((1LL << (DF_BITS(df) - 1)) - 1) +#define M_MAX_INT(m)(int64_t)((1LL << ((m) - 1)) - 1) + +#define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1))) +#define M_MIN_INT(m)(int64_t)(-(1LL << ((m) - 1))) + +#define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df))) +#define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m))) + +#define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df)) +#define SIGNED(x, df) \ +int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df))) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +static inline void msa_move_v(wr_t *pwd, wr_t *pws) +{ +uint32_t i; + +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { +pwd->d[i] = pws->d[i]; +} +} -- 1.7.4
[Qemu-devel] [PATCH v3 01/19] target-mips: add MSA defines and data structure
add defines and data structure for MIPS SIMD Architecture Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/cpu.h | 52 +- target-mips/mips-defs.h |1 + target-mips/op_helper.c |1 + 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 3b975eb..d08bbe7 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -58,12 +58,32 @@ struct CPUMIPSTLBContext { }; #endif +/* MSA Context */ +#define MSA_WRLEN (128) + +enum CPUMIPSMSADataFormat { +DF_BYTE = 0, +DF_HALF, +DF_WORD, +DF_DOUBLE +}; + +typedef union wr_t wr_t; +union wr_t { +int8_t b[MSA_WRLEN/8]; +int16_t h[MSA_WRLEN/16]; +int32_t w[MSA_WRLEN/32]; +int64_t d[MSA_WRLEN/64]; +}; + typedef union fpr_t fpr_t; union fpr_t { float64 fd; /* ieee double precision */ float32 fs[2];/* ieee single precision */ uint64_t d;/* binary double fixed-point */ uint32_t w[2]; /* binary single fixed-point */ +/* FPU/MSA register mapping is not tested on big-endian hosts. */ +wr_t wr; /* vector data */ }; /* define FP_ENDIAN_IDX to access the same location * in the fpr_t union regardless of the host endianness @@ -177,6 +197,21 @@ struct TCState { target_ulong CP0_TCScheFBack; int32_t CP0_Debug_tcstatus; target_ulong CP0_UserLocal; + +int32_t msacsr; + +#define MSACSR_FS 24 +#define MSACSR_FS_MASK (1 << MSACSR_FS) +#define MSACSR_NX 18 +#define MSACSR_NX_MASK (1 << MSACSR_NX) +#define MSACSR_CEF 2 +#define MSACSR_CEF_MASK (0x << MSACSR_CEF) +#define MSACSR_RM 0 +#define MSACSR_RM_MASK (0x3 << MSACSR_RM) +#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \ +MSACSR_FS_MASK) + +float_status msa_fp_status; }; typedef struct CPUMIPSState CPUMIPSState; @@ -192,6 +227,10 @@ struct CPUMIPSState { target_ulong SEGMask; target_ulong PAMask; +int32_t msair; +#define MSAIR_ProcID8 +#define MSAIR_Rev 0 + int32_t CP0_Index; /* CP0_MVP* are per MVP registers. */ int32_t CP0_Random; @@ -385,6 +424,7 @@ struct CPUMIPSState { #define CP0C2_SA 0 int32_t CP0_Config3; #define CP0C3_M31 +#define CP0C3_MSAP 28 #define CP0C3_BP 27 #define CP0C3_BI 26 #define CP0C3_ISA_ON_EXC 16 @@ -462,7 +502,7 @@ struct CPUMIPSState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags;/* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x5807FF +#define MIPS_HFLAG_TMASK 0x15807FF #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -508,6 +548,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_HWRENA_ULR 0x20 /* ULR bit from HWREna is set. */ #define MIPS_HFLAG_SBRI 0x40 /* R6 SDBBP causes RI excpt. in user mode */ #define MIPS_HFLAG_FBNSLOT 0x80 /* Forbidden slot */ +#define MIPS_HFLAG_MSA 0x100 target_ulong btarget;/* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -663,6 +704,8 @@ enum { EXCP_C2E, EXCP_CACHE, /* 32 */ EXCP_DSPDIS, +EXCP_MSADIS, +EXCP_MSAFPE, EXCP_TLBXI, EXCP_TLBRI, @@ -764,7 +807,7 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | - MIPS_HFLAG_SBRI); + MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -837,6 +880,11 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags |= MIPS_HFLAG_COP1X; } } +if (env->insn_flags & ASE_MSA) { +if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) { +env->hflags |= MIPS_HFLAG_MSA; +} +} } #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 6cb62b2..1784227 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -45,6 +45,7 @@ #define ASE_MT0x0020 #define ASE_SMARTMIPS 0x0040 #define ASE_MICROMIPS 0x0080 +#define ASE_MSA 0x0100 /* Chip specific instructions. */ #defineINSN_LOONGSON2E 0x2000 diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index c6de86e..0c75ec8 100644
[Qemu-devel] [PATCH v3 06/19] target-mips: add msa_reset(), global msa register
add msa_reset() and global msa register (d type only) Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/translate.c | 56 ++ target-mips/translate_init.c | 35 ++ 2 files changed, 91 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 555f89b..baa1826 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1356,6 +1356,7 @@ static TCGv cpu_dspctrl, btarget, bcond; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; +static TCGv_i64 msa_wr_d[64]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; @@ -1454,6 +1455,25 @@ static const char * const fregnames[] = { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; +static const char * const msaregnames[] = { +"w0.d0", "w0.d1", "w1.d0", "w1.d1", +"w2.d0", "w2.d1", "w3.d0", "w3.d1", +"w4.d0", "w4.d1", "w5.d0", "w5.d1", +"w6.d0", "w6.d1", "w7.d0", "w7.d1", +"w8.d0", "w8.d1", "w9.d0", "w9.d1", +"w10.d0", "w10.d1", "w11.d0", "w11.d1", +"w12.d0", "w12.d1", "w13.d0", "w13.d1", +"w14.d0", "w14.d1", "w15.d0", "w15.d1", +"w16.d0", "w16.d1", "w17.d0", "w17.d1", +"w18.d0", "w18.d1", "w19.d0", "w19.d1", +"w20.d0", "w20.d1", "w21.d0", "w21.d1", +"w22.d0", "w22.d1", "w23.d0", "w23.d1", +"w24.d0", "w24.d1", "w25.d0", "w25.d1", +"w26.d0", "w26.d1", "w27.d0", "w27.d1", +"w28.d0", "w28.d1", "w29.d0", "w29.d1", +"w30.d0", "w30.d1", "w31.d0", "w31.d1", +}; + #define MIPS_DEBUG(fmt, ...) \ do { \ if (MIPS_DEBUG_DISAS) { \ @@ -17206,6 +17226,27 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx) } } +/* MIPS SIMD Architecture (MSA) */ +static inline int check_msa_access(DisasContext *ctx) +{ +if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && + !(ctx->hflags & MIPS_HFLAG_F64))) { +generate_exception(ctx, EXCP_RI); +return 0; +} + +if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { +if (ctx->insn_flags & ASE_MSA) { +generate_exception(ctx, EXCP_MSADIS); +return 0; +} else { +generate_exception(ctx, EXCP_RI); +return 0; +} +} +return 1; +} + static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -18136,6 +18177,15 @@ void mips_tcg_init(void) fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); } +for (i = 0; i < 32; i++) { +int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); +msa_wr_d[i * 2] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); +off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); +msa_wr_d[i * 2 + 1] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]); +} + cpu_PC = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.PC), "PC"); for (i = 0; i < MIPS_DSP_ACC; i++) { @@ -18243,6 +18293,7 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; +env->msair = env->cpu_model->MSAIR; env->insn_flags = env->cpu_model->insn_flags; #if defined(CONFIG_USER_ONLY) @@ -18340,6 +18391,11 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Status |= (1 << CP0St_FR); } +/* MSA */ +if (env->CP0_Config3 & (1 << CP0C3_MSAP)) { +msa_reset(env); +} + compute_hflags(env); cs->exception_index = EXCP_NONE; } diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 0b70d05..8fb8bf8 100644 --- a/target-mips/translate_init.c +++ b/ta
[Qemu-devel] [PATCH v3 04/19] target-mips: stop translation after ctc1
stop translation as ctc1 instruction can change hflags Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/translate.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 9a8f5c9..b388ba5 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7490,12 +7490,15 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(rd); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; break; /* COP2: Not implemented. */ case 4: @@ -8089,12 +8092,15 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(fs); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; opn = "ctc1"; break; #if defined(TARGET_MIPS64) -- 1.7.4
[Qemu-devel] [PATCH v3 08/19] target-mips: add MSA branch instructions
add MSA branch instructions Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/translate.c | 334 +++ 1 files changed, 220 insertions(+), 114 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index baa1826..056a162 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17247,6 +17247,93 @@ static inline int check_msa_access(DisasContext *ctx) return 1; } +static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt) +{ +/* generates tcg ops to check if any element is 0 */ +/* Note this function only works with MSA_WRLEN = 128 */ +uint64_t eval_zero_or_big = 0; +uint64_t eval_big = 0; +TCGv_i64 t0 = tcg_temp_new_i64(); +TCGv_i64 t1 = tcg_temp_new_i64(); +switch (df) { +case DF_BYTE: +eval_zero_or_big = 0x0101010101010101ULL; +eval_big = 0x8080808080808080ULL; +break; +case DF_HALF: +eval_zero_or_big = 0x0001000100010001ULL; +eval_big = 0x8000800080008000ULL; +break; +case DF_WORD: +eval_zero_or_big = 0x00010001ULL; +eval_big = 0x80008000ULL; +break; +case DF_DOUBLE: +eval_zero_or_big = 0x0001ULL; +eval_big = 0x8000ULL; +break; +} +tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big); +tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]); +tcg_gen_andi_i64(t0, t0, eval_big); +tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big); +tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]); +tcg_gen_andi_i64(t1, t1, eval_big); +tcg_gen_or_i64(t0, t0, t1); +/* if all bits are zero then all elements are not zero */ +/* if some bit is non-zero then some element is zero */ +tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(tresult, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} + +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) +{ +uint8_t df = (ctx->opcode >> 21) & 0x3; +uint8_t wt = (ctx->opcode >> 16) & 0x1f; +int64_t s16 = (int16_t)ctx->opcode; + +check_msa_access(ctx); + +if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { +MIPS_DEBUG("CTI in delay / forbidden slot"); +generate_exception(ctx, EXCP_RI); +return; +} +switch (op1) { +case OPC_BZ_V: +case OPC_BNZ_V: +{ +TCGv_i64 t0 = tcg_temp_new_i64(); +tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]); +tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ? +TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(bcond, t0); +tcg_temp_free_i64(t0); +} +break; +case OPC_BZ_B: +case OPC_BZ_H: +case OPC_BZ_W: +case OPC_BZ_D: +gen_check_zero_element(bcond, df, wt); +break; +case OPC_BNZ_B: +case OPC_BNZ_H: +case OPC_BNZ_W: +case OPC_BNZ_D: +gen_check_zero_element(bcond, df, wt); +tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); +break; +} + +ctx->btarget = ctx->pc + (s16 << 2) + 4; + +ctx->hflags |= MIPS_HFLAG_BC; +ctx->hflags |= MIPS_HFLAG_BDS32; +} + static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -17568,133 +17655,152 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_CP1: -if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { +op1 = MASK_CP1(ctx->opcode); + +switch (op1) { +case OPC_MFHC1: +case OPC_MTHC1: check_cp1_enabled(ctx); -op1 = MASK_CP1(ctx->opcode); -switch (op1) { -case OPC_MFHC1: -case OPC_MTHC1: -check_insn(ctx, ISA_MIPS32R2); -case OPC_MFC1: -case OPC_CFC1: -case OPC_MTC1: -case OPC_CTC1: -gen_cp1(ctx, op1, rt, rd); -break; +check_insn(ctx, ISA_MIPS32R2); +case OPC_MFC1: +case OPC_CFC1: +case OPC_MTC1: +case OPC_CTC1: +check_cp1_enabled(ctx); +gen_cp1(ctx, op1, rt, rd); +break; #if defined(TARGET_MIPS64) -case OPC_DMFC1: -case OPC_DMTC1: -check_insn(ctx, ISA_MIPS3); -gen_cp1(ctx, op1, rt, rd); -break; +case OPC_DMFC1: +case OPC_DMTC1: +check_cp1_enabled(ctx); +check_insn(ctx, ISA_MIPS3); +gen_cp1(ctx, op1, rt, rd); +break; #endif -case OPC_BC1EQZ: /* OPC_BC1ANY2 */ -if (ctx->insn_flags & ISA_MIPS32R6) { -
[Qemu-devel] [PATCH v3 05/19] target-mips: add MSA opcode enum
add MSA opcode enum Reviewed-by: James Hogan Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- target-mips/translate.c | 245 +++ 1 files changed, 245 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b388ba5..555f89b 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -137,6 +137,8 @@ enum { OPC_JIALC= (0x3E << 26), /* MDMX ASE specific */ OPC_MDMX = (0x1E << 26), +/* MSA ASE, same as MDMX */ +OPC_MSA = OPC_MDMX, /* Cache and prefetch */ OPC_CACHE= (0x2F << 26), OPC_PREF = (0x33 << 26), @@ -934,6 +936,8 @@ enum { OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, +OPC_BZ_V = (0x0B << 21) | OPC_CP1, +OPC_BNZ_V= (0x0F << 21) | OPC_CP1, OPC_S_FMT= (FMT_S << 21) | OPC_CP1, OPC_D_FMT= (FMT_D << 21) | OPC_CP1, OPC_E_FMT= (FMT_E << 21) | OPC_CP1, @@ -943,6 +947,14 @@ enum { OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, OPC_BC1EQZ = (0x09 << 21) | OPC_CP1, OPC_BC1NEZ = (0x0D << 21) | OPC_CP1, +OPC_BZ_B = (0x18 << 21) | OPC_CP1, +OPC_BZ_H = (0x19 << 21) | OPC_CP1, +OPC_BZ_W = (0x1A << 21) | OPC_CP1, +OPC_BZ_D = (0x1B << 21) | OPC_CP1, +OPC_BNZ_B= (0x1C << 21) | OPC_CP1, +OPC_BNZ_H= (0x1D << 21) | OPC_CP1, +OPC_BNZ_W= (0x1E << 21) | OPC_CP1, +OPC_BNZ_D= (0x1F << 21) | OPC_CP1, }; #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) @@ -1103,6 +1115,239 @@ enum { OPC_NMSUB_PS= 0x3E | OPC_CP3, }; +/* MSA Opcodes */ +#define MASK_MSA_MINOR(op)(MASK_OP_MAJOR(op) | (op & 0x3F)) +enum { +OPC_MSA_I8_00 = 0x00 | OPC_MSA, +OPC_MSA_I8_01 = 0x01 | OPC_MSA, +OPC_MSA_I8_02 = 0x02 | OPC_MSA, +OPC_MSA_I5_06 = 0x06 | OPC_MSA, +OPC_MSA_I5_07 = 0x07 | OPC_MSA, +OPC_MSA_BIT_09 = 0x09 | OPC_MSA, +OPC_MSA_BIT_0A = 0x0A | OPC_MSA, +OPC_MSA_3R_0D = 0x0D | OPC_MSA, +OPC_MSA_3R_0E = 0x0E | OPC_MSA, +OPC_MSA_3R_0F = 0x0F | OPC_MSA, +OPC_MSA_3R_10 = 0x10 | OPC_MSA, +OPC_MSA_3R_11 = 0x11 | OPC_MSA, +OPC_MSA_3R_12 = 0x12 | OPC_MSA, +OPC_MSA_3R_13 = 0x13 | OPC_MSA, +OPC_MSA_3R_14 = 0x14 | OPC_MSA, +OPC_MSA_3R_15 = 0x15 | OPC_MSA, +OPC_MSA_ELM = 0x19 | OPC_MSA, +OPC_MSA_3RF_1A = 0x1A | OPC_MSA, +OPC_MSA_3RF_1B = 0x1B | OPC_MSA, +OPC_MSA_3RF_1C = 0x1C | OPC_MSA, +OPC_MSA_VEC = 0x1E | OPC_MSA, + +/* MI10 instruction */ +OPC_LD_B= (0x20) | OPC_MSA, +OPC_LD_H= (0x21) | OPC_MSA, +OPC_LD_W= (0x22) | OPC_MSA, +OPC_LD_D= (0x23) | OPC_MSA, +OPC_ST_B= (0x24) | OPC_MSA, +OPC_ST_H= (0x25) | OPC_MSA, +OPC_ST_W= (0x26) | OPC_MSA, +OPC_ST_D= (0x27) | OPC_MSA, +}; + +enum { +/* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ +OPC_ADDVI_df= (0x0 << 23) | OPC_MSA_I5_06, +OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, +OPC_SUBVI_df= (0x1 << 23) | OPC_MSA_I5_06, +OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, +OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, +OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, +OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, +OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, +OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, +OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, +OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, +OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, + +/* I8 instruction */ +OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, +OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, +OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, +OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, +OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, +OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, +OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, +OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, +OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02, +OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00, + +/* VEC/2R/2RF instruction */ +OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC, +OPC_OR_V= (0x01 << 21) | OPC_MSA_VEC, +OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC, +OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC, +OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC, +OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC, +OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC, + +OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC, +OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC, + +/* 2R instruction df(bits
[Qemu-devel] [PATCH v3 10/19] target-mips: add MSA I5 format instruction
add MSA I5 format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 14 + target-mips/msa_helper.c | 141 ++ target-mips/translate.c | 77 + 3 files changed, 232 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 5fd627e..072d911 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -758,3 +758,17 @@ DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32) +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32) + diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 7d4c82b..7b577e7 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -114,3 +114,144 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } +static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 + arg2; +} + +static inline int64_t msa_subv_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 - arg2; +} + +static inline int64_t msa_ceq_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 == arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 <= arg2 ? -1 : 0; +} + +static inline int64_t msa_cle_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 <= u_arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 < arg2 ? -1 : 0; +} + +static inline int64_t msa_clt_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 < u_arg2 ? -1 : 0; +} + +static inline int64_t msa_max_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 > arg2 ? arg1 : arg2; +} + +static inline int64_t msa_max_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 > u_arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_s_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +return arg1 < arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_u_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 < u_arg2 ? arg1 : arg2; +} + +#define MSA_BINOP_IMM_DF(helper, func) \ +void helper_msa_ ## helper ## _df(CPUMIPSState *env, uint32_t df, \ +uint32_t wd, uint32_t ws, int32_t u5) \ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +uint32_t i; \ +\ +switch (df) { \ +case DF_BYTE: \ +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ +pwd->b[i] = msa_ ## func ## _df(df, pws->b[i], u5); \ +} \ +break; \ +case DF_HALF: \ +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {\ +pwd->h[i] = msa_ ## func ## _df(df, pws->h[i], u5); \ +} \ +break; \ +case DF_WORD: \ +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {\ +
[Qemu-devel] [PATCH v3 14/19] target-mips: add MSA 3RF format instructions
add MSA 3RF format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 42 ++ target-mips/msa_helper.c | 1497 ++ target-mips/translate.c | 163 + 3 files changed, 1702 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index c9e033b..cee4eb4 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -858,3 +858,45 @@ DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_2(msa_cfcmsa, tl, env, i32) DEF_HELPER_3(msa_move_v, void, env, i32, i32) + +DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 3a909e6..cba7439 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -743,6 +743,29 @@ static inline int64_t msa_hsub_u_df(uint32_t df, int64_t arg1, int64_t arg2) return UNSIGNED_ODD(arg1, df) - UNSIGNED_EVEN(arg2, df); } +static inline int64_t msa_mul_q_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int64_t q_min = DF_MIN_INT(df); +int64_t q_max = DF_MAX_INT(df); + +if (arg1 == q_min && arg2 == q_min) { +return q_max; +} +return (arg1 * arg2) >> (DF_BITS(df) - 1); +} + +static inline int64_t msa_mulr_q_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int64_t q_min = DF_MIN_INT(df); +int64_t q_max = DF_MAX_INT(df); +int64_t r_bit = 1 << (DF_BITS(df) - 2); + +if (arg1 == q_min && arg2 == q_min) { +return q_max; +} +return (arg1 * arg2 + r_bit) >> (DF_BITS(df) - 1); +} + #define MSA_BINOP_DF(func) \ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ uint32_t wd, uint32_t ws, uint32_t wt) \ @@ -824,6 +847,9 @@ MSA_BINOP_DF(hadd_s) MSA_BINOP_DF(hadd_u) MSA_BINOP_DF(hsub_s) MSA_BINOP_DF(hsub_u) + +MSA_BINOP_DF(mul_q) +MSA_BINOP_DF(mulr_q) #undef MSA_BINOP_DF void helper_msa_sld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, @@ -895,6 +921,64 @@ static inline int64_t msa_dpsub_u_df(uint32_t df, int64_t dest, int64_t arg1, return dest - ((even_arg1 * even_arg2) + (odd_arg1 * odd_arg2)); } +static inline int64_t msa_madd_q_df(uint32_t df, int64_t dest, int64_t arg1, +int64_t arg2) +{ +int64_t q_prod, q_ret; + +int64_t q_max = DF_MAX_INT(df); +int64_t q_min = DF_MIN_INT(df); + +q_prod = arg1 * arg2; +q_ret = ((dest << (DF_BITS(df) - 1)) + q_prod) >> (DF_BITS(df) - 1); + +return (q_ret <
[Qemu-devel] [PATCH v3 17/19] target-mips: add MSA MI10 format instructions
add MSA MI10 format instructions update LSA and DLSA for MSA add 16, 64 bit load and store Signed-off-by: Yongbok Kim --- target-mips/helper.h|4 ++ target-mips/op_helper.c | 84 -- target-mips/translate.c | 49 +++- 3 files changed, 132 insertions(+), 5 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index cb8b40e..e0eecd1 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -929,3 +929,7 @@ DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) + +DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s32) +DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s32) + diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 7cbf4cf..034fc53 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -90,10 +90,10 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ } \ } #endif +HELPER_LD(lbu, ldub, uint8_t) +HELPER_LD(lhu, lduw, uint16_t) HELPER_LD(lw, ldl, int32_t) -#ifdef TARGET_MIPS64 HELPER_LD(ld, ldq, int64_t) -#endif #undef HELPER_LD #if defined(CONFIG_USER_ONLY) @@ -118,10 +118,9 @@ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ } #endif HELPER_ST(sb, stb, uint8_t) +HELPER_ST(sh, stw, uint16_t) HELPER_ST(sw, stl, uint32_t) -#ifdef TARGET_MIPS64 HELPER_ST(sd, stq, uint64_t) -#endif #undef HELPER_ST target_ulong helper_clo (target_ulong arg1) @@ -3626,3 +3625,80 @@ FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status) || float32_lt(fst0, fst1, &env->active_fpu.fp_status))) + +/* MSA */ +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, + int32_t s10) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); +int i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwd->b[i] = do_lbu(env, addr + (i << DF_BYTE), +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwd->h[i] = do_lhu(env, addr + (i << DF_HALF), +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_WORD: +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { +pwd->w[i] = do_lw(env, addr + (i << DF_WORD), +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_DOUBLE: +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { +pwd->d[i] = do_ld(env, addr + (i << DF_DOUBLE), +env->hflags & MIPS_HFLAG_KSU); +} +break; +} +} + +void helper_msa_st_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, + int32_t s10) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +target_ulong addr = env->active_tc.gpr[rs] + (s10 << df); +int i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +do_sb(env, addr + (i << DF_BYTE), pwd->b[i], +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +do_sh(env, addr + (i << DF_HALF), pwd->h[i], +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_WORD: +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { +do_sw(env, addr + (i << DF_WORD), pwd->w[i], +env->hflags & MIPS_HFLAG_KSU); +} +break; +case DF_DOUBLE: +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { +do_sd(env, addr + (i << DF_DOUBLE), pwd->d[i], +env->hflags & MIPS_HFLAG_KSU); +} +break; +} +} diff --git a/target-mips/translate.c b/target-mips/translate.c index 73d686e..2117ce8 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -16319,7 +16319,8 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) gen_trap(
[Qemu-devel] [PATCH v3 09/19] target-mips: add MSA I8 format instructions
add MSA I8 format instructions Reviewed-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/helper.h | 10 ++ target-mips/msa_helper.c | 67 + target-mips/translate.c | 82 - 3 files changed, 157 insertions(+), 2 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index aea12a9..5fd627e 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -748,3 +748,13 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) #endif DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) + +/* MIPS SIMD Architecture */ +DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index b65fb27..7d4c82b 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -47,3 +47,70 @@ static inline void msa_move_v(wr_t *pwd, wr_t *pws) pwd->d[i] = pws->d[i]; } } + +#define MSA_FN_IMM8(FUNC, DEST, OPERATION) \ +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ +uint32_t i8)\ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +uint32_t i; \ +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {\ +DEST = OPERATION; \ +} \ +} + +MSA_FN_IMM8(andi_b, pwd->b[i], pws->b[i] & i8) +MSA_FN_IMM8(ori_b, pwd->b[i], pws->b[i] | i8) +MSA_FN_IMM8(nori_b, pwd->b[i], ~(pws->b[i] | i8)) +MSA_FN_IMM8(xori_b, pwd->b[i], pws->b[i] ^ i8) + +#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ +UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) +MSA_FN_IMM8(bmnzi_b, pwd->b[i], +BIT_MOVE_IF_NOT_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ +UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) +MSA_FN_IMM8(bmzi_b, pwd->b[i], +BIT_MOVE_IF_ZERO(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#define BIT_SELECT(dest, arg1, arg2, df) \ +UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) +MSA_FN_IMM8(bseli_b, pwd->b[i], +BIT_SELECT(pwd->b[i], pws->b[i], i8, DF_BYTE)) + +#undef MSA_FN_IMM8 + +#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03)) + +void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t imm) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +wr_t wx, *pwx = &wx; +uint32_t i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwx->b[i] = pws->b[SHF_POS(i, imm)]; +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwx->h[i] = pws->h[SHF_POS(i, imm)]; +} +break; +case DF_WORD: +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { +pwx->w[i] = pws->w[SHF_POS(i, imm)]; +} +break; +default: +assert(0); +} +msa_move_v(pwd, pwx); +} + diff --git a/target-mips/translate.c b/target-mips/translate.c index 056a162..aba3ccb 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -17334,6 +17334,84 @@ static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) ctx->hflags |= MIPS_HFLAG_BDS32; } +static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx) +{ +#define MASK_MSA_I8(op)(MASK_MSA_MINOR(op) | (op & (0x03 << 24))) +uint8_t i8 = (ctx->opcode >> 16) & 0xff; +uint8_t ws = (ctx->opcode >> 11) & 0x1f; +uint8_t wd = (ctx->opcode >> 6) & 0x1f; + +TCGv_i32 twd = tcg_const_i32(wd); +TCGv_i32 tws = tcg_const_i32(ws); +TCGv_i32 ti8 = tcg_const_i32(i8); + +switch (MASK_MSA_I8(ctx->opcode)) { +case OPC_ANDI_B: +gen_helper_msa_andi_b(cpu_env, twd, tws, ti8); +break; +case OPC_ORI_B: +gen_helper_msa_ori_b(cpu_env, twd, tws, ti8); +
[Qemu-devel] [PATCH v3 11/19] target-mips: add MSA BIT format instructions
add MSA BIT format instructions Reviewed-by: Leon Alrae Signed-off-by: Yongbok Kim --- target-mips/helper.h | 13 +++ target-mips/msa_helper.c | 197 ++ target-mips/translate.c | 88 3 files changed, 298 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 072d911..ef0ea6d 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -772,3 +772,16 @@ DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32) DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32) DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32) +DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) + diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 7b577e7..e89027a 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -255,3 +255,200 @@ void helper_msa_ldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, assert(0); } } + +/* Data format bit position and unsigned values */ +#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) + +static inline int64_t msa_sll_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return arg1 << b_arg2; +} + +static inline int64_t msa_sra_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return arg1 >> b_arg2; +} + +static inline int64_t msa_srl_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +int32_t b_arg2 = BIT_POSITION(arg2, df); +return u_arg1 >> b_arg2; +} + +static inline int64_t msa_bclr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} + +static inline int64_t msa_bset_df(uint32_t df, int64_t arg1, +int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +static inline int64_t msa_bneg_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +static inline int64_t msa_binsl_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_dest = UNSIGNED(dest, df); +int32_t sh_d = BIT_POSITION(arg2, df) + 1; +int32_t sh_a = DF_BITS(df) - sh_d; +if (sh_d == DF_BITS(df)) { +return u_arg1; +} else { +return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 >> sh_a, df) << sh_a, df); +} +} + +static inline int64_t msa_binsr_df(uint32_t df, int64_t dest, int64_t arg1, + int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_dest = UNSIGNED(dest, df); +int32_t sh_d = BIT_POSITION(arg2, df) + 1; +int32_t sh_a = DF_BITS(df) - sh_d; +if (sh_d == DF_BITS(df)) { +return u_arg1; +} else { +return UNSIGNED(UNSIGNED(u_dest >> sh_d, df) << sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1 << sh_a, df) >> sh_a, df); +} +} + +static inline int64_t msa_sat_s_df(uint32_t df, int64_t arg, uint32_t m) +{ +return arg < M_MIN_INT(m+1) ? M_MIN_INT(m+1) : + arg > M_MAX_INT(m+1) ? M_MAX_INT(m+1) : + arg; +} + +static inline int64_t msa_sat_u_df(uint32_t df, int64_t arg, uint32_t m) +{ +uint64_t u_arg = UNSIGNED(arg, df); +return u_arg < M_MAX_UINT(m+1) ? u_arg : + M_MAX_UINT(m+1); +} + +static inline int64_t msa_srar_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +if (b_arg2 == 0) { +return arg1; +} else { +int64_t r_bit = (arg1 >> (b_arg2 - 1)) & 1; +return (arg1 >> b_arg2) + r_bit; +} +} + +static inline int64_t msa_srlr_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +int32_t b_arg2 = BIT_POSITION(arg2, df); +if (b_arg2 == 0) { +return u_arg1;
[Qemu-devel] [PATCH v3 19/19] target-mips: add MSA support to mips32r5-generic
add MSA support to mips32r5-generic core definition Signed-off-by: Yongbok Kim --- target-mips/translate_init.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 8fb8bf8..0b4b597 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -358,7 +358,7 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M), +.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M), .CP0_Config4_rw_bitmask = 0, .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), @@ -376,7 +376,7 @@ static const mips_def_t mips_defs[] = (0x93 << FCR0_PRID), .SEGBITS = 32, .PABITS = 32, -.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, +.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2 | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, #if defined(TARGET_MIPS64) -- 1.7.4
[Qemu-devel] [PATCH v3 12/19] target-mips: add MSA 3R format instructions
add MSA 3R format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 64 + target-mips/msa_helper.c | 656 ++ target-mips/translate.c | 242 + 3 files changed, 962 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index ef0ea6d..6b2d57d 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -785,3 +785,67 @@ DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) + diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index e89027a..f879cc7 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -452,3 +452,659 @@ MSA_TEROP_IMMU_DF(binsli, binsl) MSA_TEROP_IMMU_DF(binsri, binsr) #undef MSA_TEROP_IMMU_DF +static inline int64_t msa_max_a_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t abs_arg1 = arg1 >= 0 ? arg1 : -arg1; +uint64_t abs_arg2 = arg2 >= 0 ? arg2 : -arg2; +return abs_arg1 > abs_arg2 ? arg1 : arg2; +} + +static inline int64_t msa_min_a_df(uint32_t df, int64_t arg1, int64_t arg2) +{ +uint64_t abs_arg1 = arg1 >= 0 ?
[Qemu-devel] [PATCH v3 18/19] disas/mips.c: disassemble MSA instructions
disassemble MIPS SIMD Architecture instructions Signed-off-by: Yongbok Kim --- disas/mips.c | 716 +- 1 files changed, 714 insertions(+), 2 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index 4974bc0..2614c52 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -220,6 +220,28 @@ see <http://www.gnu.org/licenses/>. */ #define OP_SH_MTACC_D 13 #define OP_MASK_MTACC_D0x3 +/* MSA */ +#define OP_MASK_1BIT0x1 +#define OP_SH_1BIT 16 +#define OP_MASK_2BIT0x3 +#define OP_SH_2BIT 16 +#define OP_MASK_3BIT0x7 +#define OP_SH_3BIT 16 +#define OP_MASK_4BIT0xf +#define OP_SH_4BIT 16 +#define OP_MASK_5BIT0x1f +#define OP_SH_5BIT 16 +#define OP_MASK_10BIT 0x3ff +#define OP_SH_10BIT 11 +#define OP_MASK_MSACR11 0x1f +#define OP_SH_MSACR11 11 +#define OP_MASK_MSACR6 0x1f +#define OP_SH_MSACR66 +#define OP_MASK_GPR 0x1f +#define OP_SH_GPR 6 +#define OP_MASK_1_TO_4 0x3 +#define OP_SH_1_TO_46 + #defineOP_OP_COP0 0x10 #defineOP_OP_COP1 0x11 #defineOP_OP_COP2 0x12 @@ -510,6 +532,9 @@ struct mips_opcode /* Instruction writes MDMX accumulator. */ #define INSN2_WRITE_MDMX_ACC 0x0004 +/* Reads the general purpose register in OP_*_RD. */ +#define INSN2_READ_GPR_D0x0200 + /* Instruction is actually a macro. It should be ignored by the disassembler, and requires special treatment by the assembler. */ #define INSN_MACRO 0x @@ -567,7 +592,12 @@ struct mips_opcode #define INSN_55000x0200 /* MDMX ASE */ -#define INSN_MDMX 0x0400 +#define INSN_MDMX 0x/* Deprecated */ + +/* MIPS MSA Extension */ +#define INSN_MSA 0x0400 +#define INSN_MSA640x0400 + /* MT ASE */ #define INSN_MT 0x0800 /* SmartMIPS ASE */ @@ -1204,6 +1234,17 @@ extern const int bfd_mips16_num_opcodes; /* MIPS MT ASE support. */ #define MT32 INSN_MT +/* MSA */ +#define MSA INSN_MSA +#define MSA64 INSN_MSA64 +#define WR_VD INSN_WRITE_FPR_D/* Reuse INSN_WRITE_FPR_D */ +#define RD_VD WR_VD /* Reuse WR_VD */ +#define RD_VT INSN_READ_FPR_T /* Reuse INSN_READ_FPR_T */ +#define RD_VS INSN_READ_FPR_S /* Reuse INSN_READ_FPR_S */ +#define RD_dINSN2_READ_GPR_D/* Reuse INSN2_READ_GPR_D */ + +#define RD_rd6 0 + /* The order of overloaded instructions matters. Label arguments and register arguments look the same. Instructions that can have either for arguments must apear in the correct order in this table for the @@ -1363,6 +1404,541 @@ const struct mips_opcode mips_builtin_opcodes[] = {"cmp.sor.d", "D,S,T", 0x46a00019, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, {"cmp.sune.d", "D,S,T", 0x46a0001a, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, {"cmp.sne.d", "D,S,T", 0x46a0001b, 0xffe0003f, RD_S|RD_T|WR_D|FP_D, 0, I32R6}, + +/* MSA */ +{"sll.b", "+d,+e,+f", 0x780d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.h", "+d,+e,+f", 0x782d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.w", "+d,+e,+f", 0x784d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.d", "+d,+e,+f", 0x786d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"slli.b", "+d,+e,+7", 0x7879, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"slli.h", "+d,+e,+8", 0x7869, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"slli.w", "+d,+e,+9", 0x7849, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"slli.d", "+d,+e,'", 0x7809, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"sra.b", "+d,+e,+f", 0x788d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.h", "+d,+e,+f", 0x78ad, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.w", "+d,+e,+f", 0x78cd, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.d", "+d,+e,+f", 0x78ed, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"srai.b", "+d,+e,+7", 0x78f9, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"srai.h", "+d,+e,+8", 0x78e9, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"srai.w", "+d,+e,+9", 0x78c9, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"srai.d", "+d,+e,'", 0x7889, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"srl.b", "+d,+e,+f", 0x790d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MS
[Qemu-devel] [PATCH v3 13/19] target-mips: add MSA ELM format instructions
add MSA ELM format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h |9 +++ target-mips/msa_helper.c | 162 ++ target-mips/translate.c | 118 + 3 files changed, 289 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 6b2d57d..c9e033b 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -849,3 +849,12 @@ DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) +DEF_HELPER_2(msa_cfcmsa, tl, env, i32) +DEF_HELPER_3(msa_move_v, void, env, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index f879cc7..3a909e6 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1108,3 +1108,165 @@ MSA_FN_DF(vshf_df) #undef MSA_DO #undef MSA_LOOP_COND #undef MSA_FN_DF + +void helper_msa_sldi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +msa_sld_df(df, pwd, pws, n); +} + +void helper_msa_splati_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +msa_splat_df(df, pwd, pws, n); +} + +void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, + uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df); + +switch (df) { +case DF_BYTE: +env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: +env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: +env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: +env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; +break; +#endif +default: +assert(0); +} +} + +void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, + uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df); + +switch (df) { +case DF_BYTE: +env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: +env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: +env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: +env->active_tc.gpr[rd] = (uint64_t)env->active_fpu.fpr[ws].wr.d[n]; +break; +#endif +default: +assert(0); +} +} + +void helper_msa_insert_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t rs_num, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +target_ulong rs = env->active_tc.gpr[rs_num]; + +switch (df) { +case DF_BYTE: +pwd->b[n] = (int8_t)rs; +break; +case DF_HALF: +pwd->h[n] = (int16_t)rs; +break; +case DF_WORD: +pwd->w[n] = (int32_t)rs; +break; +case DF_DOUBLE: +pwd->d[n] = (int64_t)rs; +break; +default: +assert(0); +} +} + +void helper_msa_insve_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t n) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); + +switch (df) { +case DF_BYTE: +pwd->b[n] = (int8_t)pws->b[0]; +break; +case DF_HALF: +pwd->h[n] = (int16_t)pws->h[0]; +break; +case DF_WORD: +pwd->w[n] = (int32_t)pws->w[0]; +break; +case DF_DOUBLE: +pwd->d[n] = (int64_t)pws->d[0]; +break; +default: +assert(0); +} +} + +void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd) +{ +switch (cd) { +case 0: +break; +case 1: +env->active_tc.msacsr = (int32_t)elm & MSACSR_MASK; +/* set float_status rounding mode */ +set_float_rounding_mode( +ieee_rm[(env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR
[Qemu-devel] [PATCH v3 15/19] target-mips: add MSA VEC/2R format instructions
add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 12 target-mips/msa_helper.c | 140 ++ target-mips/translate.c | 113 + 3 files changed, 265 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index cee4eb4..3185c1d 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -900,3 +900,15 @@ DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32) + +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index cba7439..db7b7a1 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -114,6 +114,34 @@ void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } +#define MSA_FN_VECTOR(FUNC, DEST, OPERATION)\ +void helper_msa_ ## FUNC(CPUMIPSState *env, uint32_t wd, uint32_t ws, \ +uint32_t wt)\ +{ \ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); \ +wr_t *pws = &(env->active_fpu.fpr[ws].wr); \ +wr_t *pwt = &(env->active_fpu.fpr[wt].wr); \ +uint32_t i; \ +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { \ +DEST = OPERATION; \ +} \ +} + +MSA_FN_VECTOR(and_v, pwd->d[i], pws->d[i] & pwt->d[i]) +MSA_FN_VECTOR(or_v, pwd->d[i], pws->d[i] | pwt->d[i]) +MSA_FN_VECTOR(nor_v, pwd->d[i], ~(pws->d[i] | pwt->d[i])) +MSA_FN_VECTOR(xor_v, pwd->d[i], pws->d[i] ^ pwt->d[i]) +MSA_FN_VECTOR(bmnz_v, pwd->d[i], +BIT_MOVE_IF_NOT_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +MSA_FN_VECTOR(bmz_v, pwd->d[i], +BIT_MOVE_IF_ZERO(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +MSA_FN_VECTOR(bsel_v, pwd->d[i], +BIT_SELECT(pwd->d[i], pws->d[i], pwt->d[i], DF_DOUBLE)) +#undef BIT_MOVE_IF_NOT_ZERO +#undef BIT_MOVE_IF_ZERO +#undef BIT_SELECT +#undef MSA_FN_VECTOR + static inline int64_t msa_addv_df(uint32_t df, int64_t arg1, int64_t arg2) { return arg1 + arg2; @@ -1359,6 +1387,118 @@ void helper_msa_move_v(CPUMIPSState *env, uint32_t wd, uint32_t ws) msa_move_v(pwd, pws); } +static inline int64_t msa_pcnt_df(uint32_t df, int64_t arg) +{ +uint64_t x; + +x = UNSIGNED(arg, df); + +x = (x & 0xULL) + ((x >> 1) & 0xULL); +x = (x & 0xULL) + ((x >> 2) & 0xULL); +x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x >> 4) & 0x0F0F0F0F0F0F0F0FULL); +x = (x & 0x00FF00FF00FF00FFULL) + ((x >> 8) & 0x00FF00FF00FF00FFULL); +x = (x & 0xULL) + ((x >> 16) & 0xULL); +x = (x & 0xULL) + ((x >> 32)); + +return x; +} + +static inline int64_t msa_nlzc_df(uint32_t df, int64_t arg) +{ +uint64_t x, y; +int n, c; + +x = UNSIGNED(arg, df); +n = DF_BITS(df); +c = DF_BITS(df) / 2; + +do { +y = x >> c; +if (y != 0) { +n = n - c; +x = y; +} +c = c >> 1; +} while (c != 0); + +return n - x; +} + +static inline int64_t msa_nloc_df(uint32_t df, int64_t arg) +{ +return msa_nlzc_df(df, UNSIGNED((~arg), df)); +} + +void helper_msa_fill_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t rs) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +uint32_t i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwd->b[i] = (int8_t)env->active_tc.gpr[rs]; +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwd->h[i] = (int16_t)env->active
[Qemu-devel] [PATCH v3 16/19] target-mips: add MSA 2RF format instructions
add MSA 2RF format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 17 ++ target-mips/msa_helper.c | 528 ++ target-mips/translate.c | 74 +++ 3 files changed, 619 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 3185c1d..cb8b40e 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -912,3 +912,20 @@ DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) + +DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index db7b7a1..95615fe 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1498,6 +1498,7 @@ void helper_msa_ ## func ## _df(CPUMIPSState *env, uint32_t df, \ MSA_UNOP_DF(nlzc) MSA_UNOP_DF(nloc) MSA_UNOP_DF(pcnt) +#undef MSA_UNOP_DF #define FLOAT_ONE32 make_float32(0x3f8 << 20) #define FLOAT_ONE64 make_float64(0x3ffULL << 52) @@ -2905,5 +2906,532 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } +void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df, +uint32_t wd, uint32_t ws) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +if (df == DF_WORD) { +pwd->w[0] = helper_float_class_s(pws->w[0]); +pwd->w[1] = helper_float_class_s(pws->w[1]); +pwd->w[2] = helper_float_class_s(pws->w[2]); +pwd->w[3] = helper_float_class_s(pws->w[3]); +} else { +pwd->d[0] = helper_float_class_d(pws->d[0]); +pwd->d[1] = helper_float_class_d(pws->d[1]); +} +} + +#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS)\ +do {\ +int c; \ +\ +set_float_exception_flags(0, &env->active_tc.msa_fp_status);\ +DEST = float ## BITS ## _ ## OP(ARG, &env->active_tc.msa_fp_status);\ +c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \ +\ +if (get_enabled_exceptions(env, c)) { \ +DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;\ +} else if (float ## BITS ## _is_any_nan(ARG)) { \ +DEST = 0; \ +} \ +} while (0) + +void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws) +{ +wr_t wx, *pwx = &wx; +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +uint32_t i; + +clear_msacsr_cause(env); + +switch (df) { +case DF_WORD: +for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) { +MSA_FLOAT_UNOP0(pwx->w[i], to_int32_round_to_zero, pws->w[i], 32); +} +break; +case DF_DOUBLE: +for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) { +MSA_FLOAT_UNOP0(pwx->d[i], to_int64_round_to_zero, pws->d[i], 64); +} +break; +default: +assert(0); +} + +check_msacsr_cause(env); + +msa_move_v(pwd, pwx); +} + +void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws) +{ +wr_t wx, *pwx = &wx; +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +uint32_t i; + +clear_msacsr_cause(env); + +switch (df) { +case DF_WORD: +for (i = 0; i < DF_ELEMENTS
Re: [Qemu-devel] [PATCH 2/2] target-mips/translate.c: Update OPC_SYNCI
Reviewed-by: Yongbok Kim Note that there is a microMIPS version of SYNCI, it would be even better if you could update it as well. Best Regards, Yongbok Kim -Original Message- From: qemu-devel-bounces+yongbok.kim=imgtec@nongnu.org [mailto:qemu-devel-bounces+yongbok.kim=imgtec@nongnu.org] On Behalf Of Dongxue Zhang Sent: Tuesday, July 29, 2014 2:48 PM To: qemu-devel@nongnu.org Cc: peter.mayd...@linaro.org; Dongxue Zhang; aurel...@aurel32.net Subject: [Qemu-devel] [PATCH 2/2] target-mips/translate.c: Update OPC_SYNCI Update OPC_SYNCI with BS_STOP, in order to handle the instructions which saved in the same TB of the store instruction. Signed-off-by: Dongxue Zhang --- target-mips/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index c381366..dc8afcf 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15334,7 +15334,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_SYNCI: check_insn(ctx, ISA_MIPS32R2); -/* Treat as NOP. */ +/* Break the TB to be able to sync copied instructions + immediately */ +ctx->bstate = BS_STOP; break; case OPC_BPOSGE32:/* MIPS DSP branch */ #if defined(TARGET_MIPS64) -- 1.8.1.2
Re: [Qemu-devel] [PATCH 1/2] target-mips: Add synci instruction test
Tested-by: Yongbok Kim -Original Message- From: qemu-devel-bounces+yongbok.kim=imgtec@nongnu.org [mailto:qemu-devel-bounces+yongbok.kim=imgtec@nongnu.org] On Behalf Of Dongxue Zhang Sent: Tuesday, July 29, 2014 2:48 PM To: qemu-devel@nongnu.org Cc: peter.mayd...@linaro.org; Dongxue Zhang; aurel...@aurel32.net Subject: [Qemu-devel] [PATCH 1/2] target-mips: Add synci instruction test Save code with sw and raise synci. The saved code should be raise. If the code raised, log 'test passed'. If the code not raised, log 'test failed, the copied instruction not run'. Other cases, log 'unhandled'. The test should log 'test passed'. Signed-off-by: Dongxue Zhang --- tests/tcg/mips/mips64/Makefile | 54 tests/tcg/mips/mips64/head.S| 16 +++ tests/tcg/mips/mips64/io.h | 22 +++ tests/tcg/mips/mips64/mips_boot.lds | 31 + tests/tcg/mips/mips64/printf.c | 266 tests/tcg/mips/mips64/synci.c | 32 + 6 files changed, 421 insertions(+) create mode 100644 tests/tcg/mips/mips64/Makefile create mode 100644 tests/tcg/mips/mips64/head.S create mode 100644 tests/tcg/mips/mips64/io.h create mode 100644 tests/tcg/mips/mips64/mips_boot.lds create mode 100644 tests/tcg/mips/mips64/printf.c create mode 100644 tests/tcg/mips/mips64/synci.c diff --git a/tests/tcg/mips/mips64/Makefile b/tests/tcg/mips/mips64/Makefile new file mode 100644 index 000..9a222f7 --- /dev/null +++ b/tests/tcg/mips/mips64/Makefile @@ -0,0 +1,54 @@ +CROSS_COMPILE ?= mips64el-unknown-linux-gnu- + +SIM = qemu-system-mips64el +SIMFLAGS = -nographic -cpu mips64r2-generic -kernel + +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +RANLIB = $(CROSS_COMPILE)ranlib +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +VECTORS_OBJ ?= ./head.o ./printf.o + +HEAD_FLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe \ + -msoft-float -march=mips64 -Wa,-mips64 -Wa,--trap \ + -msym32 -DKBUILD_64BIT_SYM32 -I./ + +CFLAGS ?= -nostdinc -mabi=64 -G 0 -mno-abicalls -fno-pic -fno-builtin \ + -pipe -march=mips64r2 -mgp64 -mdspr2 -static -Wa,--trap -msym32 \ + -DKBUILD_64BIT_SYM32 -I./ + +LDFLAGS = -T./mips_boot.lds -L./ +FLAGS = -nostdlib -mabi=64 -march=mips64r2 -mgp64 -mdspr2 + +TESTCASES = synci.tst + +all: build + +head.o : head.S + $(Q)$(CC) $(HEAD_FLAGS) -D"STACK_TOP=0x8020" -c $< -o $@ + +%.o : %.S + $(CC) $(CFLAGS) -c $< -o $@ + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%.tst: %.o $(VECTORS_OBJ) + $(CC) $(VECTORS_OBJ) $(FLAGS) $(LDFLAGS) $< -o $@ + +build: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + +check: $(VECTORS_OBJ) $(MIPSSOC_LIB) $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIMFLAGS) ./$$case; \ + $(SIM) $(SIMFLAGS) ./$$case & (sleep 1; killall $(SIM)); \ + done + +clean: + $(Q)rm -f *.o *.tst *.a diff --git a/tests/tcg/mips/mips64/head.S b/tests/tcg/mips/mips64/head.S new file mode 100644 index 000..9a099ae --- /dev/null +++ b/tests/tcg/mips/mips64/head.S @@ -0,0 +1,16 @@ +/* + * Startup Code for MIPS64 CPU-core + * + */ +.text +.globl _start +.align 4 +_start: +ori$2, $2, 0x +sll$2, $2, 16 +ori$2, $2, 0x +mtc0 $2, $12, 0 +jalmain + +end: +b end diff --git a/tests/tcg/mips/mips64/io.h b/tests/tcg/mips/mips64/io.h new file mode 100644 index 000..b7db61d --- /dev/null +++ b/tests/tcg/mips/mips64/io.h @@ -0,0 +1,22 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H +extern int printf(const char *fmt, ...); +extern unsigned long get_ticks(void); + +#define _read(source)\ +({ unsigned long __res;\ +__asm__ __volatile__(\ +"mfc0\t%0, " #source "\n\t"\ +: "=r" (__res));\ +__res;\ +}) + +#define __read(source)\ +({ unsigned long __res;\ +__asm__ __volatile__(\ +"move\t%0, " #source "\n\t"\ +: "=r" (__res));\ +__res;\ +}) + +#endif diff --git a/tests/tcg/mips/mips64/mips_boot.lds b/tests/tcg/mips/mips64/mips_boot.lds new file mode 100644 index 000..bd7c0c0 --- /dev/null +++ b/tests/tcg/mips/mips64/mips_boot.lds @@ -0,0 +1,31 @@ +OUTPUT_ARCH(mips) +SECTIONS +{ +. = 0x8010; +. = ALIGN((1 << 13)); +.text : +{ +*(.text) +*(.rodata) +*(.rodata.*) +} + +__init_begin = .; +. = ALIGN((1 << 12)); +.init.text : AT(ADDR(.init.text) - 0) +{ +*(.init.text) +} +.ini
[Qemu-devel] [PATCH 01/20] target-mips: add MSA defines and data structure
add defines and data structure for MIPS SIMD Architecture Signed-off-by: Yongbok Kim --- target-mips/cpu.h | 79 +-- target-mips/mips-defs.h |1 + target-mips/op_helper.c |1 + 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c81dfac..9a6b77c 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -51,12 +51,74 @@ struct CPUMIPSTLBContext { }; #endif +/* MSA Context */ + +#define MSA_WRLEN (128) + +typedef union wr_t wr_t; +union wr_t { +int8_t b[MSA_WRLEN/8]; +int16_t h[MSA_WRLEN/16]; +int32_t w[MSA_WRLEN/32]; +int64_t d[MSA_WRLEN/64]; +}; + +typedef struct CPUMIPSMSAContext CPUMIPSMSAContext; +struct CPUMIPSMSAContext { + +#define MSAIR_REGISTER 0 +#define MSACSR_REGISTER 1 +#define MSAACCESS_REGISTER 2 +#define MSASAVE_REGISTER3 +#define MSAMODIFY_REGISTER 4 +#define MSAREQUEST_REGISTER 5 +#define MSAMAP_REGISTER 6 +#define MSAUNMAP_REGISTER 7 + +int32_t msair; + +#define MSAIR_WRP_POS 16 +#define MSAIR_WRP_BIT (1 << MSAIR_WRP_POS) + +int32_t msacsr; + +#define MSACSR_RM_POS 0 +#define MSACSR_RM_MASK (0x3 << MSACSR_RM_POS) + +#define MSACSR_CAUSE_ENABLE_FLAGS_POS 2 +#define MSACSR_CAUSE_ENABLE_FLAGS_MASK \ +(0x << MSACSR_CAUSE_ENABLE_FLAGS_POS) + +#define MSACSR_NX_POS 18 +#define MSACSR_NX_BIT (1 << MSACSR_NX_POS) + +#define MSACSR_FS_POS 24 +#define MSACSR_FS_BIT (1 << MSACSR_FS_POS) + +#define MSACSR_BITS \ +(MSACSR_RM_MASK | \ + MSACSR_CAUSE_ENABLE_FLAGS_MASK | \ + MSACSR_FS_BIT |\ + MSACSR_NX_BIT) + +int32_t msaaccess; +int32_t msasave; +int32_t msamodify; +int32_t msarequest; +int32_t msamap; +int32_t msaunmap; + +float_status fp_status; +}; + typedef union fpr_t fpr_t; union fpr_t { float64 fd; /* ieee double precision */ float32 fs[2];/* ieee single precision */ uint64_t d;/* binary double fixed-point */ uint32_t w[2]; /* binary single fixed-point */ +/* FPU/MSA register mapping is not tested on big-endian hosts. */ +wr_t wr; /* vector data */ }; /* define FP_ENDIAN_IDX to access the same location * in the fpr_t union regardless of the host endianness @@ -175,6 +237,7 @@ typedef struct CPUMIPSState CPUMIPSState; struct CPUMIPSState { TCState active_tc; CPUMIPSFPUContext active_fpu; +CPUMIPSMSAContext active_msa; uint32_t current_tc; uint32_t current_fpu; @@ -362,6 +425,7 @@ struct CPUMIPSState { #define CP0C2_SA 0 int32_t CP0_Config3; #define CP0C3_M31 +#define CP0C3_MSAP 28 #define CP0C3_ISA_ON_EXC 16 #define CP0C3_ULRI 13 #define CP0C3_DSPP 10 @@ -431,7 +495,7 @@ struct CPUMIPSState { int error_code; uint32_t hflags;/* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x1807FF +#define MIPS_HFLAG_TMASK 0x5807FF #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -475,6 +539,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_DSPR2 0x10 /* Enable access to MIPS DSPR2 resources. */ /* Extra flag about HWREna register. */ #define MIPS_HFLAG_HWRENA_ULR 0x20 /* ULR bit from HWREna is set. */ +#define MIPS_HFLAG_MSA 0x40 target_ulong btarget;/* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -628,8 +693,10 @@ enum { EXCP_C2E, EXCP_CACHE, /* 32 */ EXCP_DSPDIS, +EXCP_MSADIS, +EXCP_MSAFPE, -EXCP_LAST = EXCP_DSPDIS, +EXCP_LAST = EXCP_MSAFPE, }; /* Dummy exception for conditional stores. */ #define EXCP_SC 0x100 @@ -726,7 +793,8 @@ static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_UX | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); + MIPS_HFLAG_UX | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | + MIPS_HFLAG_MSA); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -784,6 +852,11 @@ static inline void compute_hflags(CPUMIPSState *env) env->hflags |= MIPS_HFLAG_COP1X; } } +if (env->insn_flags & ASE_MSA) { +if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) { +env->hflags |= MIPS_HFLAG_MSA; +} +} } #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/mips-defs.h b/target-mip
[Qemu-devel] [PATCH 03/20] target-mips: move common funcs to cpu.h
move commonly used functions to cpu.h Signed-off-by: Yongbok Kim --- target-mips/cpu.h | 72 +++ target-mips/gdbstub.c |7 target-mips/op_helper.c | 60 +- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 9a6b77c..68ce383 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -747,6 +747,10 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, #endif target_ulong exception_resume_pc (CPUMIPSState *env); +/* op_helper.c */ +extern unsigned int ieee_rm[]; +int ieee_ex_to_mips(int xcpt); + static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { @@ -859,4 +863,72 @@ static inline void compute_hflags(CPUMIPSState *env) } } +#include "exec/cpu_ldst.h" + +#if defined(CONFIG_USER_ONLY) +#define HELPER_LD(name, insn, type) \ +static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ + int mem_idx) \ +{ \ +return (type) insn##_raw(addr); \ +} +#else +#define HELPER_LD(name, insn, type) \ +static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ + int mem_idx) \ +{ \ +switch (mem_idx) { \ +case 0: \ +return (type) cpu_##insn##_kernel(env, addr); \ +break; \ +case 1: \ +return (type) cpu_##insn##_super(env, addr);\ +break; \ +default:\ +case 2: \ +return (type) cpu_##insn##_user(env, addr); \ +break; \ +} \ +} +#endif +HELPER_LD(lbu, ldub, uint8_t) +HELPER_LD(lw, ldl, int32_t) +#ifdef TARGET_MIPS64 +HELPER_LD(ld, ldq, int64_t) +#endif +#undef HELPER_LD + +#if defined(CONFIG_USER_ONLY) +#define HELPER_ST(name, insn, type) \ +static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ + type val, int mem_idx) \ +{ \ +insn##_raw(addr, val); \ +} +#else +#define HELPER_ST(name, insn, type) \ +static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ + type val, int mem_idx) \ +{ \ +switch (mem_idx) { \ +case 0: \ +cpu_##insn##_kernel(env, addr, val);\ +break; \ +case 1: \ +cpu_##insn##_super(env, addr, val); \ +break; \ +default:\ +case 2: \ +cpu_##insn##_user(env, addr, val); \ +break; \ +} \ +} +#endif +HELPER_ST(sb, stb, uint8_t) +HELPER_ST(sw, stl, uint32_t) +#ifdef TARGET_MIPS64 +HELPER_ST(sd, stq, uint64_t) +#endif +#undef HELPER_ST + #endif /* !defined (__MIPS_CPU_H__) */ diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c index 5b72d58..f65fec2 100644 --- a/target-mips/gdbstub.c +++ b/target-mips/gdbstub.c @@ -73,13 +73,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return 0; } -/* convert MIPS rounding mode in FCR31 to IEEE library */ -static unsigned int ieee_rm[] = { -float_round_nearest_even, -float_round_to_zero, -float_round_up, -float_round_down -}
[Qemu-devel] [PATCH 00/20] target-mips: add MSA module
The following patchset implements MIPS SIMD Architecture module. MSA adds new instructions to MIPS Architecture that allow efficient parallel processing of vector operations. For more information refer to: MIPS Architecture Reference Manual Volume IV-j: The MIPS32 SIMD Architecture Module The document (MD00867) is available at: http://www.imgtec.com/mips/architectures/simd.asp Note that LSA instruction is not included in this patchset as Release 6 implements it. This patchset is on top of the patch: [PATCH v2] target-mips: fix broken MIPS16 and microMIPS http://patchwork.ozlabs.org/patch/366146/ The MSA floating-point is compliant with the IEEE Standard for Floating-Point Arithmetic 754TM-2008. However this patchset is not set up with the IEEE-2008 option as QEMU softfloat for MIPS has not been updated yet. Yongbok Kim (20): target-mips: add MSA defines and data structure target-mips: add MSA exceptions target-mips: move common funcs to cpu.h target-mips: add 8, 16, 32, 64 bits load and store target-mips: stop translation after ctc1 target-mips: add MSA opcode enum target-mips: add msa_reset(), global msa register target-mips: add msa_helper.c target-mips: add MSA branch instructions target-mips: add MSA I8 format instructions target-mips: add MSA I5 format instructions target-mips: add MSA BIT format instructions target-mips: add MSA 3R format instructions target-mips: add MSA ELM format instructions target-mips: add MSA 3RF format instructions target-mips: add MSA VEC/2R format instructions target-mips: add MSA 2RF format instructions target-mips: add MSA MI10 format instructions disas/mips.c: disassemble MSA instructions target-mips: add MSA support to mips32r5-generic disas/mips.c | 721 ++- target-mips/Makefile.objs|2 +- target-mips/cpu.h| 159 ++- target-mips/gdbstub.c|7 - target-mips/helper.c |8 + target-mips/helper.h | 177 ++ target-mips/mips-defs.h |1 + target-mips/msa_helper.c | 5423 ++ target-mips/op_helper.c | 61 +- target-mips/translate.c | 1576 - target-mips/translate_init.c | 49 +- 11 files changed, 8107 insertions(+), 77 deletions(-) create mode 100644 target-mips/msa_helper.c -- 1.7.4
[Qemu-devel] [PATCH 19/20] disas/mips.c: disassemble MSA instructions
disassemble MIPS SIMD Architecture instructions Signed-off-by: Yongbok Kim --- disas/mips.c | 721 +- 1 files changed, 719 insertions(+), 2 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index 2106b57..65781f7 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -218,6 +218,28 @@ see <http://www.gnu.org/licenses/>. */ #define OP_SH_MTACC_D 13 #define OP_MASK_MTACC_D0x3 +/* MSA */ +#define OP_MASK_1BIT0x1 +#define OP_SH_1BIT 16 +#define OP_MASK_2BIT0x3 +#define OP_SH_2BIT 16 +#define OP_MASK_3BIT0x7 +#define OP_SH_3BIT 16 +#define OP_MASK_4BIT0xf +#define OP_SH_4BIT 16 +#define OP_MASK_5BIT0x1f +#define OP_SH_5BIT 16 +#define OP_MASK_10BIT 0x3ff +#define OP_SH_10BIT 11 +#define OP_MASK_MSACR11 0x1f +#define OP_SH_MSACR11 11 +#define OP_MASK_MSACR6 0x1f +#define OP_SH_MSACR66 +#define OP_MASK_GPR 0x1f +#define OP_SH_GPR 6 +#define OP_MASK_1_TO_4 0x3 +#define OP_SH_1_TO_46 + #defineOP_OP_COP0 0x10 #defineOP_OP_COP1 0x11 #defineOP_OP_COP2 0x12 @@ -502,6 +524,9 @@ struct mips_opcode /* Instruction writes MDMX accumulator. */ #define INSN2_WRITE_MDMX_ACC 0x0004 +/* Reads the general purpose register in OP_*_RD. */ +#define INSN2_READ_GPR_D0x0200 + /* Instruction is actually a macro. It should be ignored by the disassembler, and requires special treatment by the assembler. */ #define INSN_MACRO 0x @@ -557,7 +582,12 @@ struct mips_opcode #define INSN_55000x0200 /* MDMX ASE */ -#define INSN_MDMX 0x0400 +#define INSN_MDMX 0x/* Deprecated */ + +/* MIPS MSA Extension */ +#define INSN_MSA 0x0400 +#define INSN_MSA640x0400 + /* MT ASE */ #define INSN_MT 0x0800 /* SmartMIPS ASE */ @@ -1190,6 +1220,17 @@ extern const int bfd_mips16_num_opcodes; /* MIPS MT ASE support. */ #define MT32 INSN_MT +/* MSA */ +#define MSA INSN_MSA +#define MSA64 INSN_MSA64 +#define WR_VD INSN_WRITE_FPR_D/* Reuse INSN_WRITE_FPR_D */ +#define RD_VD WR_VD /* Reuse WR_VD */ +#define RD_VT INSN_READ_FPR_T /* Reuse INSN_READ_FPR_T */ +#define RD_VS INSN_READ_FPR_S /* Reuse INSN_READ_FPR_S */ +#define RD_dINSN2_READ_GPR_D/* Reuse INSN2_READ_GPR_D */ + +#define RD_rd6 0 + /* The order of overloaded instructions matters. Label arguments and register arguments look the same. Instructions that can have either for arguments must apear in the correct order in this table for the @@ -1209,6 +1250,538 @@ const struct mips_opcode mips_builtin_opcodes[] = them first. The assemblers uses a hash table based on the instruction name anyhow. */ /* name,args, match, mask, pinfo, membership */ +/* MSA */ +{"sll.b", "+d,+e,+f", 0x780d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.h", "+d,+e,+f", 0x782d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.w", "+d,+e,+f", 0x784d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sll.d", "+d,+e,+f", 0x786d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"slli.b", "+d,+e,+7", 0x7879, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"slli.h", "+d,+e,+8", 0x7869, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"slli.w", "+d,+e,+9", 0x7849, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"slli.d", "+d,+e,'", 0x7809, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"sra.b", "+d,+e,+f", 0x788d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.h", "+d,+e,+f", 0x78ad, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.w", "+d,+e,+f", 0x78cd, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"sra.d", "+d,+e,+f", 0x78ed, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"srai.b", "+d,+e,+7", 0x78f9, 0xfff8003f, WR_VD|RD_VS,0, MSA}, +{"srai.h", "+d,+e,+8", 0x78e9, 0xfff0003f, WR_VD|RD_VS,0, MSA}, +{"srai.w", "+d,+e,+9", 0x78c9, 0xffe0003f, WR_VD|RD_VS,0, MSA}, +{"srai.d", "+d,+e,'", 0x7889, 0xffc0003f, WR_VD|RD_VS,0, MSA}, +{"srl.b", "+d,+e,+f", 0x790d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"srl.h", "+d,+e,+f", 0x792d, 0xffe0003f, WR_VD|RD_VS|RD_VT, 0, MSA}, +{"srl.w", "+
[Qemu-devel] [PATCH 05/20] target-mips: stop translation after ctc1
stop translation as ctc1 instruction can change hflags Signed-off-by: Yongbok Kim --- target-mips/translate.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 994e85d..cccbc44 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6837,12 +6837,15 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, break; case 3: /* XXX: For now we support only a single FPU context. */ +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(rd); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; break; /* COP2: Not implemented. */ case 4: @@ -7278,12 +7281,15 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) break; case OPC_CTC1: gen_load_gpr(t0, rt); +save_cpu_state(ctx, 1); { TCGv_i32 fs_tmp = tcg_const_i32(fs); gen_helper_0e2i(ctc1, t0, fs_tmp, rt); tcg_temp_free_i32(fs_tmp); } +/* Stop translation as we may have changed hflags */ +ctx->bstate = BS_STOP; opn = "ctc1"; break; #if defined(TARGET_MIPS64) -- 1.7.4
[Qemu-devel] [PATCH 04/20] target-mips: add 8, 16, 32, 64 bits load and store
add 8, 16, 32, 64 bits load and store Signed-off-by: Yongbok Kim --- target-mips/cpu.h |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 68ce383..51d1c88 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -896,6 +896,10 @@ HELPER_LD(lw, ldl, int32_t) #ifdef TARGET_MIPS64 HELPER_LD(ld, ldq, int64_t) #endif +HELPER_LD(ld8, ldub, uint8_t) +HELPER_LD(ld16, lduw, uint16_t) +HELPER_LD(ld32, ldl, int32_t) +HELPER_LD(ld64, ldq, int64_t) #undef HELPER_LD #if defined(CONFIG_USER_ONLY) @@ -929,6 +933,10 @@ HELPER_ST(sw, stl, uint32_t) #ifdef TARGET_MIPS64 HELPER_ST(sd, stq, uint64_t) #endif +HELPER_ST(st8, stb, uint8_t) +HELPER_ST(st16, stw, uint16_t) +HELPER_ST(st32, stl, int32_t) +HELPER_ST(st64, stq, int64_t) #undef HELPER_ST #endif /* !defined (__MIPS_CPU_H__) */ -- 1.7.4
[Qemu-devel] [PATCH 10/20] target-mips: add MSA I8 format instructions
add MSA I8 format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 11 target-mips/msa_helper.c | 140 ++ target-mips/translate.c | 94 ++- 3 files changed, 243 insertions(+), 2 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 74ef094..174bc62 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -689,3 +689,14 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) #endif DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) + +/* MIPS SIMD Architecture */ + +DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 5afc9ae..2355809 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -194,3 +194,143 @@ static inline void msa_store_wr_elem(CPUMIPSState *env, uint64_t val, assert(0); } } + +void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +B(pwd, i) = B(pws, i) & i8; +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +B(pwd, i) = B(pws, i) | i8; +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +void helper_msa_nori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +B(pwd, i) = ~(B(pws, i) | i8); +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +B(pwd, i) = B(pws, i) ^ i8; +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +#define BIT_MOVE_IF_NOT_ZERO(dest, arg1, arg2, df) \ +dest = UNSIGNED(((dest & (~arg2)) | (arg1 & arg2)), df) + +void helper_msa_bmnzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +BIT_MOVE_IF_NOT_ZERO(B(pwd, i), B(pws, i), i8, DF_BYTE); +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +#define BIT_MOVE_IF_ZERO(dest, arg1, arg2, df) \ +dest = UNSIGNED((dest & arg2) | (arg1 & (~arg2)), df) + +void helper_msa_bmzi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +BIT_MOVE_IF_ZERO(B(pwd, i), B(pws, i), i8, DF_BYTE); +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +#define BIT_SELECT(dest, arg1, arg2, df) \ +dest = UNSIGNED((arg1 & (~dest)) | (arg2 & dest), df) + +void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t i8) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +ALL_B_ELEMENTS(i, MSA_WRLEN) { +BIT_SELECT(B(pwd, i), B(pws, i), i8, DF_BYTE); +} DONE_ALL_ELEMENTS; +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +#define SHF_POS(i, imm) ((i & 0xfc) + ((imm >> (2 * (i & 0x03))) & 0x03)) + +static inline void msa_shf_df(CPUMIPSState *env, uint32_t df, void *pwd, +void *pws, uint32_t imm) +{ +wr_
[Qemu-devel] [PATCH 02/20] target-mips: add MSA exceptions
add MSA exceptions Signed-off-by: Yongbok Kim --- target-mips/helper.c |8 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 8a997e4..ed796ff 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -396,6 +396,8 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_MDMX] = "MDMX", [EXCP_C2E] = "precise coprocessor 2", [EXCP_CACHE] = "cache error", +[EXCP_MSADIS] = "MSA disabled", +[EXCP_MSAFPE] = "MSA floating point", }; target_ulong exception_resume_pc (CPUMIPSState *env) @@ -608,12 +610,18 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_TRAP: cause = 13; goto set_EPC; +case EXCP_MSAFPE: +cause = 14; +goto set_EPC; case EXCP_FPE: cause = 15; goto set_EPC; case EXCP_C2E: cause = 18; goto set_EPC; +case EXCP_MSADIS: +cause = 21; +goto set_EPC; case EXCP_MDMX: cause = 22; goto set_EPC; -- 1.7.4
[Qemu-devel] [PATCH 08/20] target-mips: add msa_helper.c
add msa_helper.c Signed-off-by: Yongbok Kim --- target-mips/Makefile.objs |2 +- target-mips/msa_helper.c | 196 + 2 files changed, 197 insertions(+), 1 deletions(-) create mode 100644 target-mips/msa_helper.c diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs index 716244f..108fd9b 100644 --- a/target-mips/Makefile.objs +++ b/target-mips/Makefile.objs @@ -1,4 +1,4 @@ obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o -obj-y += gdbstub.o +obj-y += gdbstub.o msa_helper.o obj-$(CONFIG_SOFTMMU) += machine.o obj-$(CONFIG_KVM) += kvm.o diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c new file mode 100644 index 000..5afc9ae --- /dev/null +++ b/target-mips/msa_helper.c @@ -0,0 +1,196 @@ +/* + * MIPS SIMD Architecture Module Instruction emulation helpers for QEMU. + * + * Copyright (c) 2014 Imagination Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "cpu.h" +#include "exec/helper-proto.h" + +#define DF_BYTE 0 +#define DF_HALF 1 +#define DF_WORD 2 +#define DF_DOUBLE 3 + +static void msa_check_index(CPUMIPSState *env, +uint32_t df, uint32_t n) { +switch (df) { +case DF_BYTE: /* b */ +if (n > MSA_WRLEN / 8 - 1) { +helper_raise_exception(env, EXCP_RI); +} +break; +case DF_HALF: /* h */ +if (n > MSA_WRLEN / 16 - 1) { +helper_raise_exception(env, EXCP_RI); +} +break; +case DF_WORD: /* w */ +if (n > MSA_WRLEN / 32 - 1) { +helper_raise_exception(env, EXCP_RI); +} +break; +case DF_DOUBLE: /* d */ +if (n > MSA_WRLEN / 64 - 1) { +helper_raise_exception(env, EXCP_RI); +} +break; +default: +/* shouldn't get here */ +assert(0); +} +} + +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +#define DF_MAX_INT(df) (int64_t)((1LL << (DF_BITS(df) - 1)) - 1) +#define M_MAX_INT(m)(int64_t)((1LL << ((m) - 1)) - 1) + +#define DF_MIN_INT(df) (int64_t)(-(1LL << (DF_BITS(df) - 1))) +#define M_MIN_INT(m)(int64_t)(-(1LL << ((m) - 1))) + +#define DF_MAX_UINT(df) (uint64_t)(-1ULL >> (64 - DF_BITS(df))) +#define M_MAX_UINT(m) (uint64_t)(-1ULL >> (64 - (m))) + +/* Data format bit position and unsigned values */ +#define BIT_POSITION(x, df) ((uint64_t)(x) % DF_BITS(df)) + +#define UNSIGNED(x, df) ((x) & DF_MAX_UINT(df)) +#define SIGNED(x, df) \ +int64_t)x) << (64 - DF_BITS(df))) >> (64 - DF_BITS(df))) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df, wrlen) (wrlen / DF_BITS(df)) + +#define B(pwr, i) (((wr_t *)pwr)->b[i]) +#define BR(pwr, i) (((wr_t *)pwr)->b[i]) +#define BL(pwr, i) (((wr_t *)pwr)->b[i + MSA_WRLEN/16]) + +#define ALL_B_ELEMENTS(i, wrlen)\ +do {\ +uint32_t i; \ +for (i = wrlen / 8; i--;) + +#define H(pwr, i) (((wr_t *)pwr)->h[i]) +#define HR(pwr, i) (((wr_t *)pwr)->h[i]) +#define HL(pwr, i) (((wr_t *)pwr)->h[i + MSA_WRLEN/32]) + +#define ALL_H_ELEMENTS(i, wrlen)\ +do {\ +uint32_t i; \ +for (i = wrlen / 16; i--;) + +#define W(pwr, i) (((wr_t *)pwr)->w[i]) +#define WR(pwr, i) (((wr_t *)pwr)->w[i]) +#define WL(pwr, i) (((wr_t *)pwr)->w[i + MSA_WRLEN/64]) + +#define ALL_W_ELEMENTS(i, wrlen)\ +do {\ +uint32_t i; \ +for (i = wrlen / 32; i--;) + +#define D(pwr, i) (((wr_t *)pwr)->d[i]) +#define DR(pwr, i) (((wr_t *)pwr)->d[i]) +#define DL(pwr, i) (((wr_t *)pwr)->d[i + MSA_WRLEN/128]) + +#define ALL_D_ELEMENTS(i, wrlen)\ +do {\ +uint32_t i; \ +for (i = wrlen / 64; i--;) + +#define Q(pwr, i) (((wr_t *)pwr)->q[i]) +#define ALL_Q_ELEMENTS(i, wrlen)\ +do {
[Qemu-devel] [PATCH 11/20] target-mips: add MSA I5 format instructions
add MSA I5 format instructions: Signed-off-by: Yongbok Kim --- target-mips/helper.h | 12 ++ target-mips/msa_helper.c | 273 ++ target-mips/translate.c | 91 +++ 3 files changed, 376 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 174bc62..fe0cf48 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -692,11 +692,23 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) /* MIPS SIMD Architecture */ +DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) +DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 2355809..00b6e77 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -195,6 +195,38 @@ static inline void msa_store_wr_elem(CPUMIPSState *env, uint64_t val, } } +void helper_msa_addvi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, int64_t u5) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = (int64_t) ts + u5; +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +void helper_msa_subvi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, int64_t u5) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = (int64_t) ts - u5; +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -295,6 +327,120 @@ void helper_msa_bseli_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +static inline int64_t msa_ceq_df(CPUMIPSState *env, uint32_t df, int64_t arg1, +int64_t arg2) +{ +return arg1 == arg2 ? -1 : 0; +} + +void helper_msa_ceqi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, int64_t i5) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = msa_ceq_df(env, df, ts, i5); +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline int64_t msa_cle_s_df(CPUMIPSState *env, uint32_t df, +int64_t arg1, int64_t arg2) +{ +return arg1 <= arg2 ? -1 : 0; +} + +void helper_msa_clei_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, int64_t s5) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = msa_cle_s_df(env, df, ts, s5); +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline int64_t msa_cle_u_df(CPUMIPSState *env, uint32_t df, +int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_arg2 = UNSIGNED(arg2, df); +return u_arg1 <= u_arg2 ? -1 : 0; +} + +void helper_msa_clei_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, int64_t u5) +{ +uint64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_i64(env, ws, df, i); +td = msa_cle_u_df(env,
[Qemu-devel] [PATCH 20/20] target-mips: add MSA support to mips32r5-generic
add MSA support to mips32r5-generic core definition Signed-off-by: Yongbok Kim --- target-mips/translate_init.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 9e0f67b..034a3f8 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -355,7 +355,7 @@ static const mips_def_t mips_defs[] = (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) | (1 << CP0C1_CA), .CP0_Config2 = MIPS_CONFIG2, -.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M), +.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M), .CP0_Config4_rw_bitmask = 0, .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), @@ -373,7 +373,7 @@ static const mips_def_t mips_defs[] = (0x93 << FCR0_PRID), .SEGBITS = 32, .PABITS = 32, -.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, +.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2 | ASE_MSA, .mmu_type = MMU_TYPE_R4000, }, #if defined(TARGET_MIPS64) -- 1.7.4
[Qemu-devel] [PATCH 07/20] target-mips: add msa_reset(), global msa register
add msa_reset() and global msa register (d type only) Signed-off-by: Yongbok Kim --- target-mips/translate.c | 74 ++ target-mips/translate_init.c | 45 + 2 files changed, 119 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 6b4a82c..b8dbbdc 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1256,6 +1256,7 @@ static TCGv cpu_dspctrl, btarget, bcond; static TCGv_i32 hflags; static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; +static TCGv_i64 msa_wr_d[64]; static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; @@ -1353,6 +1354,25 @@ static const char * const fregnames[] = { "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; +static const char * const msaregnames[] = { +"w0.d0", "w0.d1", "w1.d0", "w1.d1", +"w2.d0", "w2.d1", "w3.d0", "w3.d1", +"w4.d0", "w4.d1", "w4.d0", "w4.d1", +"w6.d0", "w6.d1", "w7.d0", "w7.d1", +"w8.d0", "w8.d1", "w9.d0", "w9.d1", +"w10.d0", "w10.d1", "w11.d0", "w11.d1", +"w12.d0", "w12.d1", "w13.d0", "w13.d1", +"w14.d0", "w14.d1", "w15.d0", "w15.d1", +"w16.d0", "w16.d1", "w17.d0", "w17.d1", +"w18.d0", "w18.d1", "w19.d0", "w19.d1", +"w20.d0", "w20.d1", "w21.d0", "w21.d1", +"w22.d0", "w22.d1", "w23.d0", "w23.d1", +"w24.d0", "w24.d1", "w25.d0", "w25.d1", +"w26.d0", "w26.d1", "w27.d0", "w27.d1", +"w28.d0", "w28.d1", "w29.d0", "w29.d1", +"w30.d0", "w30.d1", "w31.d0", "w31.d1", +}; + #define MIPS_DEBUG(fmt, ...) \ do { \ if (MIPS_DEBUG_DISAS) { \ @@ -14627,6 +14647,47 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, /* End MIPSDSP functions. */ +/* MIPS SIMD Architecture (MSA) */ + +static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx, +int wt, int ws, int wd) +{ +if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) && + !(ctx->hflags & MIPS_HFLAG_F64))) { +generate_exception(ctx, EXCP_RI); +return 0; +} + +if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) { +if (ctx->insn_flags & ASE_MSA) { +generate_exception(ctx, EXCP_MSADIS); +return 0; +} else { +generate_exception(ctx, EXCP_RI); +return 0; +} +} + +if (env->active_msa.msair & MSAIR_WRP_BIT) { +int curr_request = 0; +if (wd != -1) { +curr_request |= (1 << wd); +} +if (wt != -1) { +curr_request |= (1 << wt); +} +if (ws != -1) { +curr_request |= (1 << ws); +} +env->active_msa.msarequest = curr_request +& (~env->active_msa.msaaccess | env->active_msa.msasave); +if (unlikely(env->active_msa.msarequest != 0)) { +generate_exception(ctx, EXCP_MSADIS); +return 0; +} +} +return 1; +} static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -16119,6 +16180,15 @@ void mips_tcg_init(void) fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); } +for (i = 0; i < 32; i++) { +int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); +msa_wr_d[i * 2] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); +off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); +msa_wr_d[i * 2 + 1] = +tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]); +} + cpu_PC = tcg_global_mem_new(TCG_AREG0, offsetof(CPUMIPSState, active_tc.PC), "PC"); for (i = 0; i < MIPS_DSP_ACC; i++) { @@ -16318,6 +16388,10 @@ void cpu_state_reset(CPUMIPSState *env) } } #endif +/* MSA */ +if (env->CP0_Config3 & (1 << CP0C3_MSAP
[Qemu-devel] [PATCH 12/20] target-mips: add MSA BIT format instructions
add MSA BIT format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 12 ++ target-mips/msa_helper.c | 292 ++ target-mips/translate.c | 100 3 files changed, 404 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index fe0cf48..f9406d6 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -694,9 +694,14 @@ DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s64) @@ -709,6 +714,13 @@ DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) +DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index 00b6e77..39377d6 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -279,6 +279,140 @@ void helper_msa_xori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +static inline int64_t msa_bclr_df(CPUMIPSState *env, uint32_t df, int64_t arg1, +int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); + +return UNSIGNED(arg1 & (~(1LL << b_arg2)), df); +} + +void helper_msa_bclri_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, uint32_t m) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = msa_bclr_df(env, df, ts, m); +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline int64_t msa_bneg_df(CPUMIPSState *env, uint32_t df, int64_t arg1, +int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 ^ (1LL << b_arg2), df); +} + +void helper_msa_bnegi_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, uint32_t m) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = msa_bneg_df(env, df, ts, m); +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline int64_t msa_bset_df(CPUMIPSState *env, uint32_t df, int64_t arg1, +int64_t arg2) +{ +int32_t b_arg2 = BIT_POSITION(arg2, df); +return UNSIGNED(arg1 | (1LL << b_arg2), df); +} + +void helper_msa_bseti_df(CPUMIPSState *env, uint32_t df, uint32_t wd, +uint32_t ws, uint32_t m) +{ +int64_t td, ts; +int i; +int df_bits = 8 * (1 << df); +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +ts = msa_load_wr_elem_s64(env, ws, df, i); +td = msa_bset_df(env, df, ts, m); +msa_store_wr_elem(env, td, wd, df, i); +} +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline int64_t msa_binsl_df(CPUMIPSState *env, uint32_t df, +int64_t dest, int64_t arg1, int64_t arg2) +{ +uint64_t u_arg1 = UNSIGNED(arg1, df); +uint64_t u_dest = UNSIGNED(dest, df); +int32_t sh_d = BIT_POSITION(arg2, df) + 1; +int32_t sh_a = DF_BITS(df) - sh_d; +if (sh_d == DF_BITS(df)) { +return u_arg1; +} else { +return UNSIGNED(UNSIGNED(u_dest << sh_d, df) >> sh_d, df) | + UNSIGNED(UNSIGNED(u_arg1
[Qemu-devel] [PATCH 09/20] target-mips: add MSA branch instructions
add MSA branch instructions Signed-off-by: Yongbok Kim --- target-mips/translate.c | 107 ++- 1 files changed, 105 insertions(+), 2 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b8dbbdc..0bfbcfe 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -14688,6 +14688,95 @@ static inline int check_msa_access(CPUMIPSState *env, DisasContext *ctx, } return 1; } + +static void determ_zero_element(TCGv tresult, uint8_t df, uint8_t wt) +{ +/* Note this function only works with MSA_WRLEN = 128 */ +uint64_t eval_zero_or_big; +uint64_t eval_big; +switch (df) { +case 0: /*DF_BYTE*/ +eval_zero_or_big = 0x0101010101010101ULL; +eval_big = 0x8080808080808080ULL; +break; +case 1: /*DF_HALF*/ +eval_zero_or_big = 0x0001000100010001ULL; +eval_big = 0x8000800080008000ULL; +break; +case 2: /*DF_WORD*/ +eval_zero_or_big = 0x00010001ULL; +eval_big = 0x80008000ULL; +break; +case 3: /*DF_DOUBLE*/ +eval_zero_or_big = 0x0001ULL; +eval_big = 0x8000ULL; +break; +} +TCGv_i64 t0 = tcg_temp_local_new_i64(); +TCGv_i64 t1 = tcg_temp_local_new_i64(); +tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big); +tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]); +tcg_gen_andi_i64(t0, t0, eval_big); +tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big); +tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]); +tcg_gen_andi_i64(t1, t1, eval_big); +tcg_gen_or_i64(t0, t0, t1); +/* if all bits is zero then all element is not zero */ +/* if some bit is non-zero then some element is zero */ +tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(tresult, t0); +tcg_temp_free_i64(t0); +tcg_temp_free_i64(t1); +} + +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) +{ +check_insn(ctx, ASE_MSA); + +if (ctx->hflags & MIPS_HFLAG_BMASK) { +generate_exception(ctx, EXCP_RI); +return; +} + +uint8_t df = (ctx->opcode >> 21) & 0x3 /* df [22:21] */; +uint8_t wt = (ctx->opcode >> 16) & 0x1f /* wt [20:16] */; +int64_t s16 = (ctx->opcode >> 0) & 0x /* s16 [15:0] */; +s16 = (s16 << 48) >> 48; /* sign extend s16 to 64 bits*/ + +check_msa_access(env, ctx, wt, -1, -1); + +switch (op1) { +case OPC_MSA_BZ_V: +case OPC_MSA_BNZ_V: +{ +TCGv_i64 t0 = tcg_temp_local_new_i64(); +tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]); +tcg_gen_setcondi_i64((op1 == OPC_MSA_BZ_V) ? +TCG_COND_EQ : TCG_COND_NE, t0, t0, 0); +tcg_gen_trunc_i64_tl(bcond, t0); +tcg_temp_free_i64(t0); +} +break; +case OPC_MSA_BZ_B: +case OPC_MSA_BZ_H: +case OPC_MSA_BZ_W: +case OPC_MSA_BZ_D: +determ_zero_element(bcond, df, wt); +break; +case OPC_MSA_BNZ_B: +case OPC_MSA_BNZ_H: +case OPC_MSA_BNZ_W: +case OPC_MSA_BNZ_D: +determ_zero_element(bcond, df, wt); +tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0); +break; +} + +int64_t offset = s16 << 2; +ctx->btarget = ctx->pc + offset + 4; + +ctx->hflags |= MIPS_HFLAG_BC; +} static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; @@ -15729,9 +15818,23 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_CP1: -if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { +op1 = MASK_CP1(ctx->opcode); + +if ((ctx->insn_flags & ASE_MSA) && +(op1 == OPC_MSA_BZ_V || + op1 == OPC_MSA_BNZ_V || + op1 == OPC_MSA_BZ_B || + op1 == OPC_MSA_BZ_H || + op1 == OPC_MSA_BZ_W || + op1 == OPC_MSA_BZ_D || + op1 == OPC_MSA_BNZ_B || + op1 == OPC_MSA_BNZ_H || + op1 == OPC_MSA_BNZ_W || + op1 == OPC_MSA_BNZ_D)) { +gen_msa_branch(env, ctx, op1); +} else if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { check_cp1_enabled(ctx); -op1 = MASK_CP1(ctx->opcode); + switch (op1) { case OPC_MFHC1: case OPC_MTHC1: -- 1.7.4
[Qemu-devel] [PATCH 14/20] target-mips: add MSA ELM format instructions
add MSA ELM format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h |9 ++ target-mips/msa_helper.c | 239 ++ target-mips/translate.c | 136 ++ 3 files changed, 384 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index 00705c4..e13daec 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -720,6 +720,7 @@ DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_2(msa_cfcmsa, tl, env, i32) DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s64) @@ -728,6 +729,9 @@ DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s64) +DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32) DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32) @@ -744,6 +748,8 @@ DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32) @@ -758,6 +764,7 @@ DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32) +DEF_HELPER_3(msa_move_v, void, env, i32, i32) DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) @@ -768,9 +775,11 @@ DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index bb4ea65..220a0cd 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -1166,6 +1166,59 @@ void helper_msa_clti_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_copy_s_df(CPUMIPSState *env, uint32_t df, uint32_t rd, +uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df, MSA_WRLEN); +msa_check_index(env, (uint32_t)df, (uint32_t)n); +switch (df) { +case DF_BYTE: /* b */ +env->active_tc.gpr[rd] = (int8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: /* h */ +env->active_tc.gpr[rd] = (int16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: /* w */ +env->active_tc.gpr[rd] = (int32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: /* d */ +env->active_tc.gpr[rd] = (int64_t)env->active_fpu.fpr[ws].wr.d[n]; +break; +#endif +default: +/* shouldn't get here */ +assert(0); +} +} + +void helper_msa_copy_u_df(CPUMIPSState *env, uint32_t df, uint32_t rd, +uint32_t ws, uint32_t n) +{ +n %= DF_ELEMENTS(df, MSA_WRLEN); +msa_check_index(env, (uint32_t)df, (uint32_t)n); +switch (df) { +case DF_BYTE: /* b */ +env->active_tc.gpr[rd] = (uint8_t)env->active_fpu.fpr[ws].wr.b[n]; +break; +case DF_HALF: /* h */ +env->active_tc.gpr[rd] = (uint16_t)env->active_fpu.fpr[ws].wr.h[n]; +break; +case DF_WORD: /* w */ +env->active_tc.gpr[rd] = (uint32_t)env->active_fpu.fpr[ws].wr.w[n]; +break; +#ifdef TARGET_MIPS64 +case DF_DOUBLE: /* d */
[Qemu-devel] [PATCH 06/20] target-mips: add MSA opcode enum
add MSA opcode enum Signed-off-by: Yongbok Kim --- target-mips/translate.c | 248 +++ 1 files changed, 248 insertions(+), 0 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index cccbc44..6b4a82c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -108,6 +108,8 @@ enum { OPC_SDC2 = (0x3E << 26), /* MDMX ASE specific */ OPC_MDMX = (0x1E << 26), +/* MSA ASE, same as MDMX */ +OPC_MSA = OPC_MDMX, /* Cache and prefetch */ OPC_CACHE= (0x2F << 26), OPC_PREF = (0x33 << 26), @@ -128,10 +130,12 @@ enum { OPC_ROTR = OPC_SRL | (1 << 21), OPC_SRA = 0x03 | OPC_SPECIAL, OPC_SLLV = 0x04 | OPC_SPECIAL, +OPC_MSA_S05 = 0x05 | OPC_SPECIAL, OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */ OPC_ROTRV= OPC_SRLV | (1 << 6), OPC_SRAV = 0x07 | OPC_SPECIAL, OPC_DSLLV= 0x14 | OPC_SPECIAL, +OPC_MSA_S15 = 0x15 | OPC_SPECIAL, OPC_DSRLV= 0x16 | OPC_SPECIAL, /* also DROTRV */ OPC_DROTRV = OPC_DSRLV | (1 << 6), OPC_DSRAV= 0x17 | OPC_SPECIAL, @@ -835,6 +839,8 @@ enum { OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, +OPC_MSA_BZ_V = (0x0B << 21) | OPC_CP1, +OPC_MSA_BNZ_V = (0x0F << 21) | OPC_CP1, OPC_S_FMT= (FMT_S << 21) | OPC_CP1, OPC_D_FMT= (FMT_D << 21) | OPC_CP1, OPC_E_FMT= (FMT_E << 21) | OPC_CP1, @@ -842,6 +848,14 @@ enum { OPC_W_FMT= (FMT_W << 21) | OPC_CP1, OPC_L_FMT= (FMT_L << 21) | OPC_CP1, OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, +OPC_MSA_BZ_B = (0x18 << 21) | OPC_CP1, +OPC_MSA_BZ_H = (0x19 << 21) | OPC_CP1, +OPC_MSA_BZ_W = (0x1A << 21) | OPC_CP1, +OPC_MSA_BZ_D = (0x1B << 21) | OPC_CP1, +OPC_MSA_BNZ_B = (0x1C << 21) | OPC_CP1, +OPC_MSA_BNZ_H = (0x1D << 21) | OPC_CP1, +OPC_MSA_BNZ_W = (0x1E << 21) | OPC_CP1, +OPC_MSA_BNZ_D = (0x1F << 21) | OPC_CP1, }; #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F) @@ -1000,6 +1014,240 @@ enum { OPC_NMSUB_PS= 0x3E | OPC_CP3, }; +/* MSA Opcodes */ + +#define MASK_MSA_MINOR(op)(MASK_OP_MAJOR(op) | (op & 0x3F)) +enum { +OPC_MSA_I8_00 = 0x00 | OPC_MSA, +OPC_MSA_I8_01 = 0x01 | OPC_MSA, +OPC_MSA_I8_02 = 0x02 | OPC_MSA, +OPC_MSA_I5_06 = 0x06 | OPC_MSA, +OPC_MSA_I5_07 = 0x07 | OPC_MSA, +OPC_MSA_BIT_09 = 0x09 | OPC_MSA, +OPC_MSA_BIT_0A = 0x0A | OPC_MSA, +OPC_MSA_3R_0D = 0x0D | OPC_MSA, +OPC_MSA_3R_0E = 0x0E | OPC_MSA, +OPC_MSA_3R_0F = 0x0F | OPC_MSA, +OPC_MSA_3R_10 = 0x10 | OPC_MSA, +OPC_MSA_3R_11 = 0x11 | OPC_MSA, +OPC_MSA_3R_12 = 0x12 | OPC_MSA, +OPC_MSA_3R_13 = 0x13 | OPC_MSA, +OPC_MSA_3R_14 = 0x14 | OPC_MSA, +OPC_MSA_3R_15 = 0x15 | OPC_MSA, +OPC_MSA_ELM = 0x19 | OPC_MSA, +OPC_MSA_3RF_1A = 0x1A | OPC_MSA, +OPC_MSA_3RF_1B = 0x1B | OPC_MSA, +OPC_MSA_3RF_1C = 0x1C | OPC_MSA, +OPC_MSA_VEC = 0x1E | OPC_MSA, + +/* MI10 instruction */ +OPC_MSA_LD_B= (0x20) | OPC_MSA, +OPC_MSA_LD_H= (0x21) | OPC_MSA, +OPC_MSA_LD_W= (0x22) | OPC_MSA, +OPC_MSA_LD_D= (0x23) | OPC_MSA, +OPC_MSA_ST_B= (0x24) | OPC_MSA, +OPC_MSA_ST_H= (0x25) | OPC_MSA, +OPC_MSA_ST_W= (0x26) | OPC_MSA, +OPC_MSA_ST_D= (0x27) | OPC_MSA, +}; + +enum { +/* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ +OPC_MSA_ADDVI_df= (0x0 << 23) | OPC_MSA_I5_06, +OPC_MSA_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, +OPC_MSA_SUBVI_df= (0x1 << 23) | OPC_MSA_I5_06, +OPC_MSA_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, +OPC_MSA_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, +OPC_MSA_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, +OPC_MSA_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, +OPC_MSA_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, +OPC_MSA_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, +OPC_MSA_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, +OPC_MSA_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, +OPC_MSA_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, + +/* I8 instruction */ +OPC_MSA_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, +OPC_MSA_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, +OPC_MSA_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, +OPC_MSA_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, +OPC_MSA_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, +OPC_MSA_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, +OPC_MSA_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, +OPC_MSA_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, +OPC_MSA_SHF_W = (0x2
[Qemu-devel] [PATCH 16/20] target-mips: add MSA VEC/2R format instructions
add MSA VEC/2R format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 11 ++ target-mips/msa_helper.c | 244 ++ target-mips/translate.c | 98 ++ 3 files changed, 353 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index fec21b6..b87bb50 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -698,6 +698,7 @@ DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s64) +DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32) @@ -711,10 +712,13 @@ DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32) @@ -755,6 +759,7 @@ DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) @@ -808,10 +813,15 @@ DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32) +DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32) DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32) @@ -836,4 +846,5 @@ DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32) DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index bb4ab66..aa165ac 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -495,6 +495,22 @@ void helper_msa_subsus_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +void helper_msa_and_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t wt) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +void *pwt = &(env->active_fpu.fpr[wt]); + +ALL_D_ELEMENTS(i, MSA_WRLEN) { +D(pwd, i) = D(pws, i) & D(pwt, i); +} DONE_ALL_ELEMENTS; + +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8) { @@ -508,6 +524,22 @@ void helper_msa_andi_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, } } +void helper_msa_or_v(CPUMIPSState *env, uint32_t wd, uint32_t ws, +uint32_t wt) +{ +void *pwd = &(env->active_fpu.fpr[wd]); +void *pws = &(env->active_fpu.fpr[ws]); +void *pwt = &(env->active_fpu.fpr[wt]); + +ALL_D_ELEMENTS(i, MSA_WRLEN) { +D(pwd, i) = D(pws, i) | D(pwt, i); +} DONE_ALL_ELEMENTS; + +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + void helper_msa_ori_b(CPUMIPSState *env, uint32_t wd, uint32_t ws, uint32_t i8
[Qemu-devel] [PATCH 18/20] target-mips: add MSA MI10 format instructions
add MSA MI10 format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h |2 + target-mips/msa_helper.c | 75 ++ target-mips/translate.c | 43 ++ 3 files changed, 120 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index c86bd36..89ca4d1 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -806,6 +806,7 @@ DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s64) DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32) @@ -855,6 +856,7 @@ DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32) +DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s64) DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index d152953..9827dfd 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -3240,6 +3240,81 @@ void helper_msa_msubr_q_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +static inline int64_t msa_ld_df(CPUMIPSState *env, uint32_t df_bits, +target_ulong addr) +{ +switch (df_bits) { +case 8: +return do_ld8(env, addr, env->hflags & MIPS_HFLAG_KSU); +case 16: +return do_ld16(env, addr, env->hflags & MIPS_HFLAG_KSU); +case 32: +return (int64_t) do_ld32(env, addr, env->hflags & MIPS_HFLAG_KSU); +case 64: +return (int64_t) do_ld64(env, addr, env->hflags & MIPS_HFLAG_KSU); +} +return 0; +} + +void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, +int64_t s10) +{ +int64_t td; +int df_bits = 8 * (1 << df); +int i; +target_ulong addr; +int16_t offset = s10 << df; + +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +addr = env->active_tc.gpr[rs] + offset + (i << df); +td = msa_ld_df(env, df_bits, addr); +msa_store_wr_elem(env, td, wd, df, i); +} + +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + +static inline void msa_st_df(CPUMIPSState *env, uint32_t df_bits, +target_ulong addr, int64_t val) +{ +switch (df_bits) { +case 8: +do_st8(env, addr, val, env->hflags & MIPS_HFLAG_KSU); +break; +case 16: +do_st16(env, addr, val, env->hflags & MIPS_HFLAG_KSU); +break; +case 32: +do_st32(env, addr, val, env->hflags & MIPS_HFLAG_KSU); +break; +case 64: +do_st64(env, addr, val, env->hflags & MIPS_HFLAG_KSU); +break; +} +} + +void helper_msa_st_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs, +int64_t s10) +{ +int64_t td; +int df_bits = 8 * (1 << df); +int i; +target_ulong addr; +int16_t offset = s10 << df; + +for (i = 0; i < MSA_WRLEN / df_bits; i++) { +addr = env->active_tc.gpr[rs] + offset + (i << df); +td = msa_load_wr_elem_i64(env, wd, df, i); +msa_st_df(env, df_bits, addr, td); +} + +if (env->active_msa.msair & MSAIR_WRP_BIT) { +env->active_msa.msamodify |= (1 << wd); +} +} + #define FLOAT_ONE32 make_float32(0x3f8 << 20) #define FLOAT_ONE64 make_float64(0x3ffULL << 52) diff --git a/target-mips/translate.c b/target-mips/translate.c index dcfe830..7047248 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15862,6 +15862,49 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) case OPC_MSA_VEC: gen_msa_vec(env, ctx); break; +case OPC_MSA_LD_B: +case OPC_MSA_LD_H: +case OPC_MSA_LD_W: +case OPC_MSA_LD_D: +case OPC_MSA_ST_B: +case OPC_MSA_ST_H: +case OPC_MSA_ST_W: +case OPC_MSA_ST_D: +{ +int64_t s10 = (ctx->opcode >> 16) & 0x3ff /* s10 [25:16] */; +s10 = (s10 << 54) >> 54; /* sign extend s10 to 64 bits*/ +uint8_t rs = (ctx->opcode >> 11) & 0x1f /* rs [15:11] */; +uint8_t wd = (ctx->opcode >> 6) & 0x1f /* wd [10:6] */; +uint8_t df = (ctx->opcode >> 0) & 0x3 /* df [1:0] */; + +TCGv_i32
[Qemu-devel] [PATCH 17/20] target-mips: add MSA 2RF format instructions
add MSA 2RF format instructions Signed-off-by: Yongbok Kim --- target-mips/helper.h | 16 ++ target-mips/msa_helper.c | 656 ++ target-mips/translate.c | 76 ++ 3 files changed, 748 insertions(+), 0 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index b87bb50..c86bd36 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -747,6 +747,7 @@ DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32) @@ -759,7 +760,14 @@ DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32) DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32) @@ -767,19 +775,27 @@ DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32) +DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32) DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32) DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32) diff --git a/target-mips/msa_helper.c b/target-mips/msa_helper.c index aa165ac..d152953 100644 --- a/target-mips/msa_helper.c +++ b/target-mips/msa_helper.c @@ -3240,6 +3240,9 @@ void helper_msa_msubr_q_df(CPUMIPSState *env, uint32_t df, uint32_t wd, } } +#define FLOAT_ONE32 make_float32(0x3f8 << 20) +#define FLOAT_ONE64 make_float64(0x3ffULL << 52) + #define FLOAT_SNAN16 (float16_default_nan ^ 0x0220) /* 0x7c20 */ #define FLOAT_SNAN32 (float32_default_nan ^ 0x00400020) @@ -3352,6 +3355,28 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) (!float ## BITS ## _is_zero(ARG)\ && float ## BITS ## _is_zero_or_denormal(ARG)) +#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS)\ +do {\ +int c; \ +int cause; \ +int enable; \ +\ +set_float_exception_flags(0, &env->active_msa.fp_status); \ +DEST = float ## BITS ## _ ## OP(ARG, &env->active_msa.fp_status); \ +c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \ +enable = GET_FP_ENABLE(env->active_msa.msacsr) | FP_UNIMPLEM
Re: [Qemu-devel] [PATCH v2] target-mips: fix broken MIPS16 and microMIPS
Ping! Patch for v2.1.0 -Original Message- From: Yongbok Kim Sent: 01 July 2014 17:43 To: qemu-devel@nongnu.org Cc: aurel...@aurel32.net; Leon Alrae; Cristian Cuna; Yongbok Kim Subject: [PATCH v2] target-mips: fix broken MIPS16 and microMIPS Commit 240ce26a broke MIPS16 and microMIPS support as it didn't care those branches and jumps don't have delay slot in MIPS16 and microMIPS. This patch introduces a new argument delayslot_size to the gen_compute_branch() indicating size of delay slot {0, 2, 4}. And the information is used to call handle_delay_slot() forcingly when no delay slot is required. There are some microMIPS branch and jump instructions that requires exact size of instruction in the delay slot. For indicating these instructions, MIPS_HFLAG_BDS_STRICT flag is introduced. Those fictional branch opcodes defined to support MIPS16 and microMIPS are no longer needed. Signed-off-by: Yongbok Kim --- v2: * correct MIPS_HFLAG_TMASK --- target-mips/cpu.h | 13 +- target-mips/translate.c | 284 ++- 2 files changed, 117 insertions(+), 180 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 8b9a92e..c81dfac 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -431,7 +431,7 @@ struct CPUMIPSState { int error_code; uint32_t hflags;/* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0xC07FF +#define MIPS_HFLAG_TMASK 0x1807FF #define MIPS_HFLAG_MODE 0x7 /* execution modes*/ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -463,17 +463,18 @@ struct CPUMIPSState { #define MIPS_HFLAG_BL 0x01800 /* Likely branch */ #define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */ /* Extra flags about the current pending branch. */ -#define MIPS_HFLAG_BMASK_EXT 0x3C000 +#define MIPS_HFLAG_BMASK_EXT 0x7C000 #define MIPS_HFLAG_B160x04000 /* branch instruction was 16 bits */ #define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */ #define MIPS_HFLAG_BDS32 0x1 /* branch requires 32-bit delay slot */ -#define MIPS_HFLAG_BX 0x2 /* branch exchanges execution mode*/ +#define MIPS_HFLAG_BDS_STRICT 0x2 /* Strict delay slot size */ +#define MIPS_HFLAG_BX 0x4 /* branch exchanges execution mode*/ #define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT) /* MIPS DSP resources access. */ -#define MIPS_HFLAG_DSP 0x4 /* Enable access to MIPS DSP resources. */ -#define MIPS_HFLAG_DSPR2 0x8 /* Enable access to MIPS DSPR2 resources. */ +#define MIPS_HFLAG_DSP 0x08 /* Enable access to MIPS DSP resources. */ +#define MIPS_HFLAG_DSPR2 0x10 /* Enable access to MIPS DSPR2 resources. */ /* Extra flag about HWREna register. */ -#define MIPS_HFLAG_HWRENA_ULR 0x10 /* ULR bit from HWREna is set. */ +#define MIPS_HFLAG_HWRENA_ULR 0x20 /* ULR bit from HWREna is set. */ target_ulong btarget;/* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ diff --git a/target-mips/translate.c b/target-mips/translate.c index 2f91959..a654ae8 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -61,7 +61,6 @@ enum { /* Jump and branches */ OPC_J= (0x02 << 26), OPC_JAL = (0x03 << 26), -OPC_JALS = OPC_JAL | 0x5, OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ OPC_BEQL = (0x14 << 26), OPC_BNE = (0x05 << 26), @@ -70,8 +69,7 @@ enum { OPC_BLEZL= (0x16 << 26), OPC_BGTZ = (0x07 << 26), OPC_BGTZL= (0x17 << 26), -OPC_JALX = (0x1D << 26), /* MIPS 16 only */ -OPC_JALXS= OPC_JALX | 0x5, +OPC_JALX = (0x1D << 26), /* Load and stores */ OPC_LDL = (0x1A << 26), OPC_LDR = (0x1B << 26), @@ -171,8 +169,6 @@ enum { /* Jumps */ OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ -OPC_JALRC= OPC_JALR | (0x5 << 6), -OPC_JALRS= 0x10 | OPC_SPECIAL | (0x5 << 6), /* Traps */ OPC_TGE = 0x30 | OPC_SPECIAL, OPC_TGEU = 0x31 | OPC_SPECIAL, @@ -236,10 +232,8 @@ enum { OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, OPC_BGEZL= (0x03 << 16) | OPC_REGIMM, OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, -OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */ OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, -OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */ OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM, OPC_TGEI = (0x08 <
Re: [Qemu-devel] [PATCH] target-mips: fix for missing delay slot in BC1EQZ and BC1NEZ
On 06/11/2014 10:29, Leon Alrae wrote: New R6 COP1 conditional branches currently don't have delay slot. Fixing this by setting MIPS_HFLAG_BDS32 flag which is required for branches having 4-byte delay slot. Signed-off-by: Leon Alrae --- target-mips/translate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-mips/translate.c b/target-mips/translate.c index 2117ce8..e83c50a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8104,6 +8104,7 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, ctx->hflags, btarget); ctx->btarget = btarget; +ctx->hflags |= MIPS_HFLAG_BDS32; out: tcg_temp_free_i64(t0); Reviewed-by: Yongbok Kim Regards, Yongbok Kim
Re: [Qemu-devel] [PATCH v2 10/20] target-mips: add MSA I8 format instructions
On 05/11/2014 17:43, Richard Henderson wrote: On 10/29/2014 02:41 AM, Yongbok Kim wrote: +void helper_msa_shf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, + uint32_t ws, uint32_t imm) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +wr_t *pws = &(env->active_fpu.fpr[ws].wr); +wr_t wx, *pwx = &wx; +uint32_t i; + +switch (df) { +case DF_BYTE: +for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) { +pwx->b[i] = pws->b[SHF_POS(i, imm)]; +} +break; +case DF_HALF: +for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) { +pwx->h[i] = pws->h[SHF_POS(i, imm)]; +} +break; Why pass DF to decode at runtime? It's better to fully decode this at translate time and call the correct function. r~ Hi Richard, Agreed. DF is already known in translation time. I do have a plan to improve efficiency of MSA implementation. Regards, Yongbok
[Qemu-devel] [PATCH] target-mips: fix multiple TCG registers covering same data
Avoid to allocate different TCG registers for the FPU registers that are mapped on the MSA vectore registers. Signed-off-by: Yongbok Kim --- target-mips/translate.c |8 +++- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index b43b286..95d8071 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -20200,14 +20200,12 @@ void mips_tcg_init(void) regnames[i]); for (i = 0; i < 32; i++) { -int off = offsetof(CPUMIPSState, active_fpu.fpr[i]); -fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]); -} - -for (i = 0; i < 32; i++) { int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]); msa_wr_d[i * 2] = tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]); +/* The scalar floating-point unit (FPU) registers are mapped on + * the MSA vector registers. */ +fpu_f64[i] = msa_wr_d[i * 2]; off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]); msa_wr_d[i * 2 + 1] = tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]); -- 1.7.4
[Qemu-devel] running 64 bit user mode program on 32 bit host machine
Hi All, I have faced a problem to run a simple 64 bit Linux user mode application on 32 bit Linux host machines. I did some investigation and found out that the TARGET_ELF_PAGESTART macro in the linux-user/elfload.c is causing the problem. However I am not sure if this is the right solution as I am not familiar with the area. Perhaps the macro should take care of target’s bits width rather than just use unsigned long. Would you please confirm the change or suggest better solution? Regards, Yongbok $ ../masterbin/mips64-linux-user/qemu-mips64 -cpu MIPS64R6-generic ./hello_linux.elf qemu: uncaught target signal 11 (Segmentation fault) - core dumped Segmentation fault (core dumped) $ git diff diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 399c021..d99a43b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1227,7 +1227,7 @@ struct exec /* Necessary parameters */ #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE -#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) +#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1)) #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) #define DLINFO_ITEMS 14 (END) WITH the change: $ ../masterbin/mips64-linux-user/qemu-mips64 -cpu MIPS64R6-generic ./hello_linux.elf Hello World!
[Qemu-devel] [PATCH] linux-user: Use abi_ulong for TARGET_ELF_PAGESTART
TARGET_ELF_PAGESTART is required to use abi_ulong to correctly handle addresses for different target bits width. This patch fixes a problem when running a 64-bit user mode application on 32-bit host machines. Signed-off-by: Yongbok Kim Reviewed-by: Peter Maydell --- linux-user/elfload.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 399c021..edf0cf4 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1227,7 +1227,8 @@ struct exec /* Necessary parameters */ #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE -#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) +#define TARGET_ELF_PAGESTART(_v) ((_v) & \ + ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1)) #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) #define DLINFO_ITEMS 14 -- 1.7.5.4
[Qemu-devel] [PATCH v4 2/3] softmmu: Add probe_write()
Add probe_write() forces a tlb_fill if the specified guest virtual index isn't in the TCG softmmu TLB. Signed-off-by: Yongbok Kim --- include/exec/exec-all.h |2 ++ softmmu_template.h | 21 + 2 files changed, 23 insertions(+), 0 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index b58cd47..af51203 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -109,6 +109,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, hwaddr paddr, MemTxAttrs attrs, int prot, int mmu_idx, target_ulong size); void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr); +void probe_write(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t retaddr); #else static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) { diff --git a/softmmu_template.h b/softmmu_template.h index 39f571b..c175d17 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -548,6 +548,27 @@ glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, helper_te_st_name(env, addr, val, oi, GETRA()); } +#if DATA_SIZE == 1 +/* + * Force a tlb_fill if the specified guest virtual index isn't in the TCG + * softmmu TLB. + */ +void probe_write(CPUArchState *env, target_ulong addr, int mmu_idx, + uintptr_t retaddr) +{ +int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); +target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; + +if ((addr & TARGET_PAGE_MASK) +!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { +/* TLB entry is for a different page */ +if (!VICTIM_TLB_HIT(addr_write)) { +tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr); +} +} +return; +} +#endif #endif /* !defined(SOFTMMU_CODE_ACCESS) */ #undef READ_ACCESS_TYPE -- 1.7.5.4
[Qemu-devel] [PATCH v4 0/3] target-mips: Add support for misaligned accesses
This patch set adds support for misaligned memory accesses in MIPS architecture Release 6 and MIPS SIMD Architecture. The behaviour, semantics, and architecture specifications of misaligned memory accesses are described in: MIPS Architecture For Programmers Volume I-A: Introduction to the MIPS64 Architecture, Appendix B Misaligned Memory Accesses. Available at http://www.imgtec.com/mips/architectures/mips64.asp Regards, Yongbok v4: * Removed the work-around per the recent TCG change for misaligned accesses * Added probe_write() (Richard) * Used helper_ret_*_mmu directly (Richard) * Removed TLB checking for MSA LD (Richard) * Removed unnecessary save_cpu_state() calls v3: * Rewrote MSA patch * Work-around is using byte-to-byte accesses and endianness corrections for R5+MSA. (This replaces the misaligned flag from v2.) (Leon) * Bug fixes (Leon) * Separate helper functions for each data formats v2: * Removed re-translation in the mips_cpu_do_unaligned_access() (Peter) * Checks validity only if an access is spanning into two pages in MSA (Leon) * Introduced misaligned flag to indicate MSA ld/st is ongoing, is used to allow misaligned accesses in the mips_cpu_do_unaligned_access() callback. This is crucial to support MSA misaligned accesses in Release 5 cores. Yongbok Kim (3): target-mips: Misaligned memory accesses for R6 softmmu: Add probe_write() target-mips: Misaligned memory accesses for MSA include/exec/exec-all.h |2 + softmmu_template.h | 21 ++ target-mips/helper.h | 10 +++- target-mips/op_helper.c | 144 +++-- target-mips/translate.c | 21 -- target-mips/translate_init.c |2 +- 6 files changed, 127 insertions(+), 73 deletions(-) -- 1.7.5.4