提交 e2e6fa67 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-aug-2018' into staging

MIPS queue August 2018 v6

# gpg: Signature made Fri 24 Aug 2018 16:52:27 BST
# gpg:                using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01  DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-aug-2018: (45 commits)
  target/mips: Add definition of nanoMIPS I7200 CPU
  mips_malta: Fix semihosting argument passing for nanoMIPS bare metal
  mips_malta: Add setting up GT64120 BARs to the nanoMIPS bootloader
  mips_malta: Add basic nanoMIPS boot code for Malta board
  elf: Don't check FCR31_NAN2008 bit for nanoMIPS
  elf: On elf loading, treat both EM_MIPS and EM_NANOMIPS as legal for MIPS
  elf: Relax MIPS' elf_check_arch() to accept EM_NANOMIPS too
  elf: Add EM_NANOMIPS value as a valid one for e_machine field
  target/mips: Fix ERET/ERETNC behavior related to ADEL exception
  target/mips: Add updating BadInstr and BadInstrX for nanoMIPS
  target/mips: Add availability control via bit NMS
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 6
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 5
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 4
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 3
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 2
  target/mips: Add emulation of DSP ASE for nanoMIPS - part 1
  target/mips: Implement MT ASE support for nanoMIPS
  target/mips: Fix pre-nanoMIPS MT ASE instructions availability control
  target/mips: Add emulation of nanoMIPS 32-bit branch instructions
  ...
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -599,6 +599,208 @@ static void network_init(PCIBus *pci_bus)
}
}
static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr,
int64_t kernel_entry)
{
uint16_t *p;
/* Small bootloader */
p = (uint16_t *)base;
#define NM_HI1(VAL) (((VAL) >> 16) & 0x1f)
#define NM_HI2(VAL) \
(((VAL) & 0xf000) | (((VAL) >> 19) & 0xffc) | (((VAL) >> 31) & 0x1))
#define NM_LO(VAL) ((VAL) & 0xfff)
stw_p(p++, 0x2800); stw_p(p++, 0x001c);
/* bc to_here */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
/* to_here: */
if (semihosting_get_argc()) {
/* Preserve a0 content as arguments have been passed */
stw_p(p++, 0x8000); stw_p(p++, 0xc000);
/* nop */
} else {
stw_p(p++, 0x0080); stw_p(p++, 0x0002);
/* li a0,2 */
}
stw_p(p++, 0xe3a0 | NM_HI1(ENVP_ADDR - 64));
stw_p(p++, NM_HI2(ENVP_ADDR - 64));
/* lui sp,%hi(ENVP_ADDR - 64) */
stw_p(p++, 0x83bd); stw_p(p++, NM_LO(ENVP_ADDR - 64));
/* ori sp,sp,%lo(ENVP_ADDR - 64) */
stw_p(p++, 0xe0a0 | NM_HI1(ENVP_ADDR));
stw_p(p++, NM_HI2(ENVP_ADDR));
/* lui a1,%hi(ENVP_ADDR) */
stw_p(p++, 0x80a5); stw_p(p++, NM_LO(ENVP_ADDR));
/* ori a1,a1,%lo(ENVP_ADDR) */
stw_p(p++, 0xe0c0 | NM_HI1(ENVP_ADDR + 8));
stw_p(p++, NM_HI2(ENVP_ADDR + 8));
/* lui a2,%hi(ENVP_ADDR + 8) */
stw_p(p++, 0x80c6); stw_p(p++, NM_LO(ENVP_ADDR + 8));
/* ori a2,a2,%lo(ENVP_ADDR + 8) */
stw_p(p++, 0xe0e0 | NM_HI1(loaderparams.ram_low_size));
stw_p(p++, NM_HI2(loaderparams.ram_low_size));
/* lui a3,%hi(loaderparams.ram_low_size) */
stw_p(p++, 0x80e7); stw_p(p++, NM_LO(loaderparams.ram_low_size));
/* ori a3,a3,%lo(loaderparams.ram_low_size) */
/*
* Load BAR registers as done by YAMON:
*
* - set up PCI0 I/O BARs from 0x18000000 to 0x181fffff
* - set up PCI0 MEM0 at 0x10000000, size 0x8000000
* - set up PCI0 MEM1 at 0x18200000, size 0xbe00000
*
*/
stw_p(p++, 0xe040); stw_p(p++, 0x0681);
/* lui t1, %hi(0xb4000000) */
#ifdef TARGET_WORDS_BIGENDIAN
stw_p(p++, 0xe020); stw_p(p++, 0x0be1);
/* lui t0, %hi(0xdf000000) */
/* 0x68 corresponds to GT_ISD (from hw/mips/gt64xxx_pci.c) */
stw_p(p++, 0x8422); stw_p(p++, 0x9068);
/* sw t0, 0x68(t1) */
stw_p(p++, 0xe040); stw_p(p++, 0x077d);
/* lui t1, %hi(0xbbe00000) */
stw_p(p++, 0xe020); stw_p(p++, 0x0801);
/* lui t0, %hi(0xc0000000) */
/* 0x48 corresponds to GT_PCI0IOLD */
stw_p(p++, 0x8422); stw_p(p++, 0x9048);
/* sw t0, 0x48(t1) */
stw_p(p++, 0xe020); stw_p(p++, 0x0800);
/* lui t0, %hi(0x40000000) */
/* 0x50 corresponds to GT_PCI0IOHD */
stw_p(p++, 0x8422); stw_p(p++, 0x9050);
/* sw t0, 0x50(t1) */
stw_p(p++, 0xe020); stw_p(p++, 0x0001);
/* lui t0, %hi(0x80000000) */
/* 0x58 corresponds to GT_PCI0M0LD */
stw_p(p++, 0x8422); stw_p(p++, 0x9058);
/* sw t0, 0x58(t1) */
stw_p(p++, 0xe020); stw_p(p++, 0x07e0);
/* lui t0, %hi(0x3f000000) */
/* 0x60 corresponds to GT_PCI0M0HD */
stw_p(p++, 0x8422); stw_p(p++, 0x9060);
/* sw t0, 0x60(t1) */
stw_p(p++, 0xe020); stw_p(p++, 0x0821);
/* lui t0, %hi(0xc1000000) */
/* 0x80 corresponds to GT_PCI0M1LD */
stw_p(p++, 0x8422); stw_p(p++, 0x9080);
/* sw t0, 0x80(t1) */
stw_p(p++, 0xe020); stw_p(p++, 0x0bc0);
/* lui t0, %hi(0x5e000000) */
#else
stw_p(p++, 0x0020); stw_p(p++, 0x00df);
/* addiu[32] t0, $0, 0xdf */
/* 0x68 corresponds to GT_ISD */
stw_p(p++, 0x8422); stw_p(p++, 0x9068);
/* sw t0, 0x68(t1) */
/* Use kseg2 remapped address 0x1be00000 */
stw_p(p++, 0xe040); stw_p(p++, 0x077d);
/* lui t1, %hi(0xbbe00000) */
stw_p(p++, 0x0020); stw_p(p++, 0x00c0);
/* addiu[32] t0, $0, 0xc0 */
/* 0x48 corresponds to GT_PCI0IOLD */
stw_p(p++, 0x8422); stw_p(p++, 0x9048);
/* sw t0, 0x48(t1) */
stw_p(p++, 0x0020); stw_p(p++, 0x0040);
/* addiu[32] t0, $0, 0x40 */
/* 0x50 corresponds to GT_PCI0IOHD */
stw_p(p++, 0x8422); stw_p(p++, 0x9050);
/* sw t0, 0x50(t1) */
stw_p(p++, 0x0020); stw_p(p++, 0x0080);
/* addiu[32] t0, $0, 0x80 */
/* 0x58 corresponds to GT_PCI0M0LD */
stw_p(p++, 0x8422); stw_p(p++, 0x9058);
/* sw t0, 0x58(t1) */
stw_p(p++, 0x0020); stw_p(p++, 0x003f);
/* addiu[32] t0, $0, 0x3f */
/* 0x60 corresponds to GT_PCI0M0HD */
stw_p(p++, 0x8422); stw_p(p++, 0x9060);
/* sw t0, 0x60(t1) */
stw_p(p++, 0x0020); stw_p(p++, 0x00c1);
/* addiu[32] t0, $0, 0xc1 */
/* 0x80 corresponds to GT_PCI0M1LD */
stw_p(p++, 0x8422); stw_p(p++, 0x9080);
/* sw t0, 0x80(t1) */
stw_p(p++, 0x0020); stw_p(p++, 0x005e);
/* addiu[32] t0, $0, 0x5e */
#endif
/* 0x88 corresponds to GT_PCI0M1HD */
stw_p(p++, 0x8422); stw_p(p++, 0x9088);
/* sw t0, 0x88(t1) */
stw_p(p++, 0xe320 | NM_HI1(kernel_entry));
stw_p(p++, NM_HI2(kernel_entry));
/* lui t9,%hi(kernel_entry) */
stw_p(p++, 0x8339); stw_p(p++, NM_LO(kernel_entry));
/* ori t9,t9,%lo(kernel_entry) */
stw_p(p++, 0x4bf9); stw_p(p++, 0x0000);
/* jalrc t8 */
}
/* ROM and pseudo bootloader
The following code implements a very very simple bootloader. It first
......@@ -620,7 +822,6 @@ static void network_init(PCIBus *pci_bus)
a2 - 32-bit address of the environment variables table
a3 - RAM size in bytes
*/
static void write_bootloader(uint8_t *base, int64_t run_addr,
int64_t kernel_entry)
{
......@@ -1096,8 +1297,13 @@ void mips_malta_init(MachineState *machine)
loaderparams.initrd_filename = initrd_filename;
kernel_entry = load_kernel();
write_bootloader(memory_region_get_ram_ptr(bios),
bootloader_run_addr, kernel_entry);
if (!cpu_supports_isa(machine->cpu_type, ISA_NANOMIPS32)) {
write_bootloader(memory_region_get_ram_ptr(bios),
bootloader_run_addr, kernel_entry);
} else {
write_bootloader_nanomips(memory_region_get_ram_ptr(bios),
bootloader_run_addr, kernel_entry);
}
if (kvm_enabled()) {
/* Write the bootloader code @ the end of RAM, 1MB reserved */
write_bootloader(memory_region_get_ram_ptr(ram_low_preio) +
......
......@@ -143,6 +143,8 @@ typedef int64_t Elf64_Sxword;
#define EM_RISCV 243 /* RISC-V */
#define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */
/*
* This is an interim value that we will use until the committee comes
* up with a final number.
......
......@@ -327,6 +327,14 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
}
break;
case EM_MIPS:
case EM_NANOMIPS:
if ((ehdr.e_machine != EM_MIPS) &&
(ehdr.e_machine != EM_NANOMIPS)) {
ret = ELF_LOAD_WRONG_ARCH;
goto fail;
}
break;
default:
if (elf_machine != ehdr.e_machine) {
ret = ELF_LOAD_WRONG_ARCH;
......
......@@ -853,6 +853,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
#endif
#define ELF_ARCH EM_MIPS
#define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS)
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
......
......@@ -397,10 +397,13 @@ static int do_store_exclusive(CPUMIPSState *env)
target_ulong addr;
target_ulong page_addr;
target_ulong val;
uint32_t val_wp = 0;
uint32_t llnewval_wp = 0;
int flags;
int segv = 0;
int reg;
int d;
int wp;
addr = env->lladdr;
page_addr = addr & TARGET_PAGE_MASK;
......@@ -412,19 +415,31 @@ static int do_store_exclusive(CPUMIPSState *env)
} else {
reg = env->llreg & 0x1f;
d = (env->llreg & 0x20) != 0;
if (d) {
segv = get_user_s64(val, addr);
wp = (env->llreg & 0x40) != 0;
if (!wp) {
if (d) {
segv = get_user_s64(val, addr);
} else {
segv = get_user_s32(val, addr);
}
} else {
segv = get_user_s32(val, addr);
segv |= get_user_s32(val_wp, addr);
llnewval_wp = env->llnewval_wp;
}
if (!segv) {
if (val != env->llval) {
if (val != env->llval && val_wp == llnewval_wp) {
env->active_tc.gpr[reg] = 0;
} else {
if (d) {
segv = put_user_u64(env->llnewval, addr);
if (!wp) {
if (d) {
segv = put_user_u64(env->llnewval, addr);
} else {
segv = put_user_u32(env->llnewval, addr);
}
} else {
segv = put_user_u32(env->llnewval, addr);
segv |= put_user_u32(env->llnewval_wp, addr + 4);
}
if (!segv) {
env->active_tc.gpr[reg] = 1;
......@@ -732,6 +747,9 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
if (regs->cp0_epc & 1) {
env->hflags |= MIPS_HFLAG_M16;
}
if (env->insn_flags & ISA_NANOMIPS32) {
return;
}
if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
if ((env->active_fpu.fcr31_rw_bitmask &
......
......@@ -506,6 +506,8 @@ struct CPUMIPSState {
uint64_t lladdr;
target_ulong llval;
target_ulong llnewval;
uint64_t llval_wp;
uint32_t llnewval_wp;
target_ulong llreg;
uint64_t CP0_LLAddr_rw_bitmask;
int CP0_LLAddr_shift;
......
......@@ -682,6 +682,22 @@ static void set_hflags_for_handler (CPUMIPSState *env)
static inline void set_badinstr_registers(CPUMIPSState *env)
{
if (env->insn_flags & ISA_NANOMIPS32) {
if (env->CP0_Config3 & (1 << CP0C3_BI)) {
uint32_t instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16;
if ((instr & 0x10000000) == 0) {
instr |= cpu_lduw_code(env, env->active_tc.PC + 2);
}
env->CP0_BadInstr = instr;
if ((instr & 0xFC000000) == 0x60000000) {
instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16;
env->CP0_BadInstrX = instr;
}
}
return;
}
if (env->hflags & MIPS_HFLAG_M16) {
/* TODO: add BadInstr support for microMIPS */
return;
......
......@@ -40,6 +40,8 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
#endif
DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
#ifndef CONFIG_USER_ONLY
/* CP0 helpers */
DEF_HELPER_1(mfc0_mvpcontrol, tl, env)
......
......@@ -39,6 +39,7 @@
#define ISA_MIPS64R5 0x00001000
#define ISA_MIPS32R6 0x00002000
#define ISA_MIPS64R6 0x00004000
#define ISA_NANOMIPS32 0x00008000
/* MIPS ASEs. */
#define ASE_MIPS16 0x00010000
......@@ -87,6 +88,9 @@
#define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6)
#define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6)
/* Wave Computing: "nanoMIPS" */
#define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32)
/* Strictly follow the architecture standard:
- Disallow "special" instruction handling for PMON/SPIM.
Note that we still maintain Count/Compare to match the host clock. */
......
......@@ -249,6 +249,100 @@ target_ulong helper_bitswap(target_ulong rt)
return (int32_t)bitswap(rt);
}
target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx,
uint32_t stripe)
{
int i;
uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff);
uint64_t tmp1 = tmp0;
for (i = 0; i <= 46; i++) {
int s;
if (i & 0x8) {
s = shift;
} else {
s = shiftx;
}
if (stripe != 0 && !(i & 0x4)) {
s = ~s;
}
if (s & 0x10) {
if (tmp0 & (1LL << (i + 16))) {
tmp1 |= 1LL << i;
} else {
tmp1 &= ~(1LL << i);
}
}
}
uint64_t tmp2 = tmp1;
for (i = 0; i <= 38; i++) {
int s;
if (i & 0x4) {
s = shift;
} else {
s = shiftx;
}
if (s & 0x8) {
if (tmp1 & (1LL << (i + 8))) {
tmp2 |= 1LL << i;
} else {
tmp2 &= ~(1LL << i);
}
}
}
uint64_t tmp3 = tmp2;
for (i = 0; i <= 34; i++) {
int s;
if (i & 0x2) {
s = shift;
} else {
s = shiftx;
}
if (s & 0x4) {
if (tmp2 & (1LL << (i + 4))) {
tmp3 |= 1LL << i;
} else {
tmp3 &= ~(1LL << i);
}
}
}
uint64_t tmp4 = tmp3;
for (i = 0; i <= 32; i++) {
int s;
if (i & 0x1) {
s = shift;
} else {
s = shiftx;
}
if (s & 0x2) {
if (tmp3 & (1LL << (i + 2))) {
tmp4 |= 1LL << i;
} else {
tmp4 &= ~(1LL << i);
}
}
}
uint64_t tmp5 = tmp4;
for (i = 0; i <= 31; i++) {
int s;
s = shift;
if (s & 0x1) {
if (tmp4 & (1LL << (i + 1))) {
tmp5 |= 1LL << i;
} else {
tmp5 &= ~(1LL << i);
}
}
}
return (int64_t)(int32_t)(uint32_t)tmp5;
}
#ifndef CONFIG_USER_ONLY
static inline hwaddr do_translate_address(CPUMIPSState *env,
......@@ -2333,10 +2427,12 @@ void helper_eretnc(CPUMIPSState *env)
void helper_deret(CPUMIPSState *env)
{
debug_pre_eret(env);
set_pc(env, env->CP0_DEPC);
env->hflags &= ~MIPS_HFLAG_DM;
compute_hflags(env);
set_pc(env, env->CP0_DEPC);
debug_post_eret(env);
}
#endif /* !CONFIG_USER_ONLY */
......
此差异已折叠。
......@@ -449,6 +449,45 @@ const mips_def_t mips_defs[] =
.insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS,
.mmu_type = MMU_TYPE_R4000,
},
{
.name = "I7200",
.CP0_PRid = 0x00010000,
.CP0_Config0 = MIPS_CONFIG0 | (1 << CP0C0_MM) | (0x2 << CP0C0_AR) |
(MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = (1U << CP0C1_M) | (15 << CP0C1_MMU) | (2 << CP0C1_IS) |
(4 << CP0C1_IL) | (3 << CP0C1_IA) | (2 << CP0C1_DS) |
(4 << CP0C1_DL) | (3 << CP0C1_DA) | (1 << CP0C1_PC) |
(1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_CMGCR) |
(1 << CP0C3_BI) | (1 << CP0C3_SC) | (3 << CP0C3_MMAR) |
(1 << CP0C3_ISA_ON_EXC) | (1 << CP0C3_ISA) |
(1 << CP0C3_ULRI) | (1 << CP0C3_RXI) |
(1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) |
(1 << CP0C3_CTXTC) | (1 << CP0C3_VInt) |
(1 << CP0C3_CDMM) | (1 << CP0C3_MT) | (1 << CP0C3_TL),
.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
(2 << CP0C4_IE) | (1U << CP0C4_M),
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_MVH) | (1 << CP0C5_LLB),
.CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
(1 << CP0C5_UFE),
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x3158FF1F,
.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
(1U << CP0PG_RIE),
.CP0_PageGrain_rw_bitmask = 0,
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
(1 << FCR0_S) | (0x02 << FCR0_PRID) | (0x0 << FCR0_REV),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_NANOMIPS32 | ASE_DSP | ASE_DSPR2 | ASE_MT,
.mmu_type = MMU_TYPE_R4000,
},
#if defined(TARGET_MIPS64)
{
.name = "R4000",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册