Merge branch 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa
* 'xtensa' of git://jcmvbkbc.spb.ru/dumb/qemu-xtensa: target-xtensa: add breakpoint tests target-xtensa: add DEBUG_SECTION to overlay tool target-xtensa: add DBREAK data breakpoints exec: let cpu_watchpoint_insert accept larger watchpoints exec: fix check_watchpoint exiting cpu_loop exec: add missing breaks to the watch_mem_write target-xtensa: add ICOUNT SR and debug exception target-xtensa: implement instruction breakpoints target-xtensa: add DEBUGCAUSE SR and configuration target-xtensa: fetch 3rd opcode byte only when needed target-xtensa: implement info tlb monitor command target-xtensa: define TLB_TEMPLATE for MMU-less cores
This commit is contained in:
		
						commit
						b3e54c689c
					
				
							
								
								
									
										18
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								exec.c
									
									
									
									
									
								
							@ -1504,7 +1504,8 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
 | 
				
			|||||||
    CPUWatchpoint *wp;
 | 
					    CPUWatchpoint *wp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
 | 
					    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
 | 
				
			||||||
    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
 | 
					    if ((len & (len - 1)) || (addr & ~len_mask) ||
 | 
				
			||||||
 | 
					            len == 0 || len > TARGET_PAGE_SIZE) {
 | 
				
			||||||
        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
 | 
					        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
 | 
				
			||||||
                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
 | 
					                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
 | 
				
			||||||
        return -EINVAL;
 | 
					        return -EINVAL;
 | 
				
			||||||
@ -3331,12 +3332,13 @@ static void check_watchpoint(int offset, int len_mask, int flags)
 | 
				
			|||||||
                tb_phys_invalidate(tb, -1);
 | 
					                tb_phys_invalidate(tb, -1);
 | 
				
			||||||
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
 | 
					                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
 | 
				
			||||||
                    env->exception_index = EXCP_DEBUG;
 | 
					                    env->exception_index = EXCP_DEBUG;
 | 
				
			||||||
 | 
					                    cpu_loop_exit(env);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
 | 
					                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
 | 
				
			||||||
                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
 | 
					                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                    cpu_resume_from_signal(env, NULL);
 | 
					                    cpu_resume_from_signal(env, NULL);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            wp->flags &= ~BP_WATCHPOINT_HIT;
 | 
					            wp->flags &= ~BP_WATCHPOINT_HIT;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -3363,9 +3365,15 @@ static void watch_mem_write(void *opaque, target_phys_addr_t addr,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
 | 
					    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
 | 
				
			||||||
    switch (size) {
 | 
					    switch (size) {
 | 
				
			||||||
    case 1: stb_phys(addr, val);
 | 
					    case 1:
 | 
				
			||||||
    case 2: stw_phys(addr, val);
 | 
					        stb_phys(addr, val);
 | 
				
			||||||
    case 4: stl_phys(addr, val);
 | 
					        break;
 | 
				
			||||||
 | 
					    case 2:
 | 
				
			||||||
 | 
					        stw_phys(addr, val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 4:
 | 
				
			||||||
 | 
					        stl_phys(addr, val);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    default: abort();
 | 
					    default: abort();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1355,7 +1355,7 @@ show i8259 (PIC) state
 | 
				
			|||||||
@item info pci
 | 
					@item info pci
 | 
				
			||||||
show emulated PCI device info
 | 
					show emulated PCI device info
 | 
				
			||||||
@item info tlb
 | 
					@item info tlb
 | 
				
			||||||
show virtual to physical memory mappings (i386, SH4, SPARC, and PPC only)
 | 
					show virtual to physical memory mappings (i386, SH4, SPARC, PPC, and Xtensa only)
 | 
				
			||||||
@item info mem
 | 
					@item info mem
 | 
				
			||||||
show the active virtual memory mappings (i386 only)
 | 
					show the active virtual memory mappings (i386 only)
 | 
				
			||||||
@item info jit
 | 
					@item info jit
 | 
				
			||||||
 | 
				
			|||||||
@ -1949,7 +1949,7 @@ static void tlb_info(Monitor *mon)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
 | 
					#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA)
 | 
				
			||||||
static void tlb_info(Monitor *mon)
 | 
					static void tlb_info(Monitor *mon)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CPUState *env1 = mon_get_cpu();
 | 
					    CPUState *env1 = mon_get_cpu();
 | 
				
			||||||
@ -2396,7 +2396,7 @@ static mon_cmd_t info_cmds[] = {
 | 
				
			|||||||
        .mhandler.info = hmp_info_pci,
 | 
					        .mhandler.info = hmp_info_pci,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
 | 
					#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
 | 
				
			||||||
    defined(TARGET_PPC)
 | 
					    defined(TARGET_PPC) || defined(TARGET_XTENSA)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        .name       = "tlb",
 | 
					        .name       = "tlb",
 | 
				
			||||||
        .args_type  = "",
 | 
					        .args_type  = "",
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@ static const XtensaConfig dc232b = {
 | 
				
			|||||||
    EXCEPTIONS_SECTION,
 | 
					    EXCEPTIONS_SECTION,
 | 
				
			||||||
    INTERRUPTS_SECTION,
 | 
					    INTERRUPTS_SECTION,
 | 
				
			||||||
    TLB_SECTION,
 | 
					    TLB_SECTION,
 | 
				
			||||||
 | 
					    DEBUG_SECTION,
 | 
				
			||||||
    .clock_freq_khz = 10000,
 | 
					    .clock_freq_khz = 10000,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ static const XtensaConfig fsf = {
 | 
				
			|||||||
    EXCEPTIONS_SECTION,
 | 
					    EXCEPTIONS_SECTION,
 | 
				
			||||||
    INTERRUPTS_SECTION,
 | 
					    INTERRUPTS_SECTION,
 | 
				
			||||||
    TLB_SECTION,
 | 
					    TLB_SECTION,
 | 
				
			||||||
 | 
					    DEBUG_SECTION,
 | 
				
			||||||
    .clock_freq_khz = 10000,
 | 
					    .clock_freq_khz = 10000,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -126,6 +126,10 @@ enum {
 | 
				
			|||||||
    RASID = 90,
 | 
					    RASID = 90,
 | 
				
			||||||
    ITLBCFG = 91,
 | 
					    ITLBCFG = 91,
 | 
				
			||||||
    DTLBCFG = 92,
 | 
					    DTLBCFG = 92,
 | 
				
			||||||
 | 
					    IBREAKENABLE = 96,
 | 
				
			||||||
 | 
					    IBREAKA = 128,
 | 
				
			||||||
 | 
					    DBREAKA = 144,
 | 
				
			||||||
 | 
					    DBREAKC = 160,
 | 
				
			||||||
    EPC1 = 177,
 | 
					    EPC1 = 177,
 | 
				
			||||||
    DEPC = 192,
 | 
					    DEPC = 192,
 | 
				
			||||||
    EPS2 = 194,
 | 
					    EPS2 = 194,
 | 
				
			||||||
@ -137,8 +141,11 @@ enum {
 | 
				
			|||||||
    PS = 230,
 | 
					    PS = 230,
 | 
				
			||||||
    VECBASE = 231,
 | 
					    VECBASE = 231,
 | 
				
			||||||
    EXCCAUSE = 232,
 | 
					    EXCCAUSE = 232,
 | 
				
			||||||
 | 
					    DEBUGCAUSE = 233,
 | 
				
			||||||
    CCOUNT = 234,
 | 
					    CCOUNT = 234,
 | 
				
			||||||
    PRID = 235,
 | 
					    PRID = 235,
 | 
				
			||||||
 | 
					    ICOUNT = 236,
 | 
				
			||||||
 | 
					    ICOUNTLEVEL = 237,
 | 
				
			||||||
    EXCVADDR = 238,
 | 
					    EXCVADDR = 238,
 | 
				
			||||||
    CCOMPARE = 240,
 | 
					    CCOMPARE = 240,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -161,12 +168,27 @@ enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define PS_WOE 0x40000
 | 
					#define PS_WOE 0x40000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_IC 0x1
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_IB 0x2
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_DB 0x4
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_BI 0x8
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_BN 0x10
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_DI 0x20
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_DBNUM 0xf00
 | 
				
			||||||
 | 
					#define DEBUGCAUSE_DBNUM_SHIFT 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DBREAKC_SB 0x80000000
 | 
				
			||||||
 | 
					#define DBREAKC_LB 0x40000000
 | 
				
			||||||
 | 
					#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
 | 
				
			||||||
 | 
					#define DBREAKC_MASK 0x3f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_NAREG 64
 | 
					#define MAX_NAREG 64
 | 
				
			||||||
#define MAX_NINTERRUPT 32
 | 
					#define MAX_NINTERRUPT 32
 | 
				
			||||||
#define MAX_NLEVEL 6
 | 
					#define MAX_NLEVEL 6
 | 
				
			||||||
#define MAX_NNMI 1
 | 
					#define MAX_NNMI 1
 | 
				
			||||||
#define MAX_NCCOMPARE 3
 | 
					#define MAX_NCCOMPARE 3
 | 
				
			||||||
#define MAX_TLB_WAY_SIZE 8
 | 
					#define MAX_TLB_WAY_SIZE 8
 | 
				
			||||||
 | 
					#define MAX_NDBREAK 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REGION_PAGE_MASK 0xe0000000
 | 
					#define REGION_PAGE_MASK 0xe0000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -186,6 +208,7 @@ enum {
 | 
				
			|||||||
    EXC_KERNEL,
 | 
					    EXC_KERNEL,
 | 
				
			||||||
    EXC_USER,
 | 
					    EXC_USER,
 | 
				
			||||||
    EXC_DOUBLE,
 | 
					    EXC_DOUBLE,
 | 
				
			||||||
 | 
					    EXC_DEBUG,
 | 
				
			||||||
    EXC_MAX
 | 
					    EXC_MAX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -279,6 +302,11 @@ typedef struct XtensaConfig {
 | 
				
			|||||||
    uint32_t timerint[MAX_NCCOMPARE];
 | 
					    uint32_t timerint[MAX_NCCOMPARE];
 | 
				
			||||||
    unsigned nextint;
 | 
					    unsigned nextint;
 | 
				
			||||||
    unsigned extint[MAX_NINTERRUPT];
 | 
					    unsigned extint[MAX_NINTERRUPT];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned debug_level;
 | 
				
			||||||
 | 
					    unsigned nibreak;
 | 
				
			||||||
 | 
					    unsigned ndbreak;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t clock_freq_khz;
 | 
					    uint32_t clock_freq_khz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xtensa_tlb itlb;
 | 
					    xtensa_tlb itlb;
 | 
				
			||||||
@ -310,6 +338,9 @@ typedef struct CPUXtensaState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int exception_taken;
 | 
					    int exception_taken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Watchpoints for DBREAK registers */
 | 
				
			||||||
 | 
					    CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CPU_COMMON
 | 
					    CPU_COMMON
 | 
				
			||||||
} CPUXtensaState;
 | 
					} CPUXtensaState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -344,6 +375,8 @@ void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
 | 
				
			|||||||
int xtensa_get_physical_addr(CPUState *env,
 | 
					int xtensa_get_physical_addr(CPUState *env,
 | 
				
			||||||
        uint32_t vaddr, int is_write, int mmu_idx,
 | 
					        uint32_t vaddr, int is_write, int mmu_idx,
 | 
				
			||||||
        uint32_t *paddr, uint32_t *page_size, unsigned *access);
 | 
					        uint32_t *paddr, uint32_t *page_size, unsigned *access);
 | 
				
			||||||
 | 
					void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
 | 
				
			||||||
 | 
					void debug_exception_env(CPUState *new_env, uint32_t cause);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 | 
					#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 | 
				
			||||||
@ -409,6 +442,8 @@ static inline int cpu_mmu_index(CPUState *env)
 | 
				
			|||||||
#define XTENSA_TBFLAG_RING_MASK 0x3
 | 
					#define XTENSA_TBFLAG_RING_MASK 0x3
 | 
				
			||||||
#define XTENSA_TBFLAG_EXCM 0x4
 | 
					#define XTENSA_TBFLAG_EXCM 0x4
 | 
				
			||||||
#define XTENSA_TBFLAG_LITBASE 0x8
 | 
					#define XTENSA_TBFLAG_LITBASE 0x8
 | 
				
			||||||
 | 
					#define XTENSA_TBFLAG_DEBUG 0x10
 | 
				
			||||||
 | 
					#define XTENSA_TBFLAG_ICOUNT 0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 | 
					static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 | 
				
			||||||
        target_ulong *cs_base, int *flags)
 | 
					        target_ulong *cs_base, int *flags)
 | 
				
			||||||
@ -424,6 +459,14 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 | 
				
			|||||||
            (env->sregs[LITBASE] & 1)) {
 | 
					            (env->sregs[LITBASE] & 1)) {
 | 
				
			||||||
        *flags |= XTENSA_TBFLAG_LITBASE;
 | 
					        *flags |= XTENSA_TBFLAG_LITBASE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
 | 
				
			||||||
 | 
					        if (xtensa_get_cintlevel(env) < env->config->debug_level) {
 | 
				
			||||||
 | 
					            *flags |= XTENSA_TBFLAG_DEBUG;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
 | 
				
			||||||
 | 
					            *flags |= XTENSA_TBFLAG_ICOUNT;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "cpu-all.h"
 | 
					#include "cpu-all.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ void cpu_reset(CPUXtensaState *env)
 | 
				
			|||||||
    env->sregs[PS] = xtensa_option_enabled(env->config,
 | 
					    env->sregs[PS] = xtensa_option_enabled(env->config,
 | 
				
			||||||
            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
 | 
					            XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
 | 
				
			||||||
    env->sregs[VECBASE] = env->config->vecbase;
 | 
					    env->sregs[VECBASE] = env->config->vecbase;
 | 
				
			||||||
 | 
					    env->sregs[IBREAKENABLE] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    env->pending_irq_level = 0;
 | 
					    env->pending_irq_level = 0;
 | 
				
			||||||
    reset_mmu(env);
 | 
					    reset_mmu(env);
 | 
				
			||||||
@ -57,9 +58,44 @@ void xtensa_register_core(XtensaConfigList *node)
 | 
				
			|||||||
    xtensa_cores = node;
 | 
					    xtensa_cores = node;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t check_hw_breakpoints(CPUState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < env->config->ndbreak; ++i) {
 | 
				
			||||||
 | 
					        if (env->cpu_watchpoint[i] &&
 | 
				
			||||||
 | 
					                env->cpu_watchpoint[i]->flags & BP_WATCHPOINT_HIT) {
 | 
				
			||||||
 | 
					            return DEBUGCAUSE_DB | (i << DEBUGCAUSE_DBNUM_SHIFT);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static CPUDebugExcpHandler *prev_debug_excp_handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void breakpoint_handler(CPUState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (env->watchpoint_hit) {
 | 
				
			||||||
 | 
					        if (env->watchpoint_hit->flags & BP_CPU) {
 | 
				
			||||||
 | 
					            uint32_t cause;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            env->watchpoint_hit = NULL;
 | 
				
			||||||
 | 
					            cause = check_hw_breakpoints(env);
 | 
				
			||||||
 | 
					            if (cause) {
 | 
				
			||||||
 | 
					                debug_exception_env(env, cause);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            cpu_resume_from_signal(env, NULL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (prev_debug_excp_handler) {
 | 
				
			||||||
 | 
					        prev_debug_excp_handler(env);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 | 
					CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static int tcg_inited;
 | 
					    static int tcg_inited;
 | 
				
			||||||
 | 
					    static int debug_handler_inited;
 | 
				
			||||||
    CPUXtensaState *env;
 | 
					    CPUXtensaState *env;
 | 
				
			||||||
    const XtensaConfig *config = NULL;
 | 
					    const XtensaConfig *config = NULL;
 | 
				
			||||||
    XtensaConfigList *core = xtensa_cores;
 | 
					    XtensaConfigList *core = xtensa_cores;
 | 
				
			||||||
@ -83,6 +119,12 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 | 
				
			|||||||
        xtensa_translate_init();
 | 
					        xtensa_translate_init();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!debug_handler_inited && tcg_enabled()) {
 | 
				
			||||||
 | 
					        debug_handler_inited = 1;
 | 
				
			||||||
 | 
					        prev_debug_excp_handler =
 | 
				
			||||||
 | 
					            cpu_set_debug_excp_handler(breakpoint_handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xtensa_irq_init(env);
 | 
					    xtensa_irq_init(env);
 | 
				
			||||||
    qemu_init_vcpu(env);
 | 
					    qemu_init_vcpu(env);
 | 
				
			||||||
    return env;
 | 
					    return env;
 | 
				
			||||||
@ -193,6 +235,7 @@ void do_interrupt(CPUState *env)
 | 
				
			|||||||
    case EXC_KERNEL:
 | 
					    case EXC_KERNEL:
 | 
				
			||||||
    case EXC_USER:
 | 
					    case EXC_USER:
 | 
				
			||||||
    case EXC_DOUBLE:
 | 
					    case EXC_DOUBLE:
 | 
				
			||||||
 | 
					    case EXC_DEBUG:
 | 
				
			||||||
        qemu_log_mask(CPU_LOG_INT, "%s(%d) "
 | 
					        qemu_log_mask(CPU_LOG_INT, "%s(%d) "
 | 
				
			||||||
                "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
 | 
					                "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
 | 
				
			||||||
                __func__, env->exception_index,
 | 
					                __func__, env->exception_index,
 | 
				
			||||||
@ -540,3 +583,70 @@ int xtensa_get_physical_addr(CPUState *env,
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dump_tlb(FILE *f, fprintf_function cpu_fprintf,
 | 
				
			||||||
 | 
					        CPUState *env, bool dtlb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned wi, ei;
 | 
				
			||||||
 | 
					    const xtensa_tlb *conf =
 | 
				
			||||||
 | 
					        dtlb ? &env->config->dtlb : &env->config->itlb;
 | 
				
			||||||
 | 
					    unsigned (*attr_to_access)(uint32_t) =
 | 
				
			||||||
 | 
					        xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) ?
 | 
				
			||||||
 | 
					        mmu_attr_to_access : region_attr_to_access;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (wi = 0; wi < conf->nways; ++wi) {
 | 
				
			||||||
 | 
					        uint32_t sz = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1;
 | 
				
			||||||
 | 
					        const char *sz_text;
 | 
				
			||||||
 | 
					        bool print_header = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (sz >= 0x100000) {
 | 
				
			||||||
 | 
					            sz >>= 20;
 | 
				
			||||||
 | 
					            sz_text = "MB";
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            sz >>= 10;
 | 
				
			||||||
 | 
					            sz_text = "KB";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (ei = 0; ei < conf->way_size[wi]; ++ei) {
 | 
				
			||||||
 | 
					            const xtensa_tlb_entry *entry =
 | 
				
			||||||
 | 
					                xtensa_tlb_get_entry(env, dtlb, wi, ei);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (entry->asid) {
 | 
				
			||||||
 | 
					                unsigned access = attr_to_access(entry->attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (print_header) {
 | 
				
			||||||
 | 
					                    print_header = false;
 | 
				
			||||||
 | 
					                    cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text);
 | 
				
			||||||
 | 
					                    cpu_fprintf(f,
 | 
				
			||||||
 | 
					                            "\tVaddr       Paddr       ASID  Attr RWX\n"
 | 
				
			||||||
 | 
					                            "\t----------  ----------  ----  ---- ---\n");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                cpu_fprintf(f,
 | 
				
			||||||
 | 
					                        "\t0x%08x  0x%08x  0x%02x  0x%02x %c%c%c\n",
 | 
				
			||||||
 | 
					                        entry->vaddr,
 | 
				
			||||||
 | 
					                        entry->paddr,
 | 
				
			||||||
 | 
					                        entry->asid,
 | 
				
			||||||
 | 
					                        entry->attr,
 | 
				
			||||||
 | 
					                        (access & PAGE_READ) ? 'R' : '-',
 | 
				
			||||||
 | 
					                        (access & PAGE_WRITE) ? 'W' : '-',
 | 
				
			||||||
 | 
					                        (access & PAGE_EXEC) ? 'X' : '-');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (xtensa_option_bits_enabled(env->config,
 | 
				
			||||||
 | 
					                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
 | 
				
			||||||
 | 
					                XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION) |
 | 
				
			||||||
 | 
					                XTENSA_OPTION_BIT(XTENSA_OPTION_MMU))) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cpu_fprintf(f, "ITLB:\n");
 | 
				
			||||||
 | 
					        dump_tlb(f, cpu_fprintf, env, false);
 | 
				
			||||||
 | 
					        cpu_fprintf(f, "\nDTLB:\n");
 | 
				
			||||||
 | 
					        dump_tlb(f, cpu_fprintf, env, true);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        cpu_fprintf(f, "No TLB for this CPU core\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
DEF_HELPER_1(exception, void, i32)
 | 
					DEF_HELPER_1(exception, void, i32)
 | 
				
			||||||
DEF_HELPER_2(exception_cause, void, i32, i32)
 | 
					DEF_HELPER_2(exception_cause, void, i32, i32)
 | 
				
			||||||
DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
 | 
					DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
 | 
				
			||||||
 | 
					DEF_HELPER_2(debug_exception, void, i32, i32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_HELPER_1(nsa, i32, i32)
 | 
					DEF_HELPER_1(nsa, i32, i32)
 | 
				
			||||||
DEF_HELPER_1(nsau, i32, i32)
 | 
					DEF_HELPER_1(nsau, i32, i32)
 | 
				
			||||||
DEF_HELPER_1(wsr_windowbase, void, i32)
 | 
					DEF_HELPER_1(wsr_windowbase, void, i32)
 | 
				
			||||||
@ -29,4 +31,9 @@ DEF_HELPER_2(itlb, void, i32, i32)
 | 
				
			|||||||
DEF_HELPER_2(ptlb, i32, i32, i32)
 | 
					DEF_HELPER_2(ptlb, i32, i32, i32)
 | 
				
			||||||
DEF_HELPER_3(wtlb, void, i32, i32, i32)
 | 
					DEF_HELPER_3(wtlb, void, i32, i32, i32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEF_HELPER_1(wsr_ibreakenable, void, i32)
 | 
				
			||||||
 | 
					DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
 | 
				
			||||||
 | 
					DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
 | 
				
			||||||
 | 
					DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "def-helper.h"
 | 
					#include "def-helper.h"
 | 
				
			||||||
 | 
				
			|||||||
@ -134,6 +134,27 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
 | 
				
			|||||||
    HELPER(exception_cause)(pc, cause);
 | 
					    HELPER(exception_cause)(pc, cause);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void debug_exception_env(CPUState *new_env, uint32_t cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
 | 
				
			||||||
 | 
					        env = new_env;
 | 
				
			||||||
 | 
					        HELPER(debug_exception)(env->pc, cause);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned level = env->config->debug_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    env->pc = pc;
 | 
				
			||||||
 | 
					    env->sregs[DEBUGCAUSE] = cause;
 | 
				
			||||||
 | 
					    env->sregs[EPC1 + level - 1] = pc;
 | 
				
			||||||
 | 
					    env->sregs[EPS2 + level - 2] = env->sregs[PS];
 | 
				
			||||||
 | 
					    env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | PS_EXCM |
 | 
				
			||||||
 | 
					        (level << PS_INTLEVEL_SHIFT);
 | 
				
			||||||
 | 
					    HELPER(exception)(EXC_DEBUG);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t HELPER(nsa)(uint32_t v)
 | 
					uint32_t HELPER(nsa)(uint32_t v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (v & 0x80000000) {
 | 
					    if (v & 0x80000000) {
 | 
				
			||||||
@ -662,3 +683,82 @@ void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
 | 
				
			|||||||
    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
 | 
					    split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
 | 
				
			||||||
    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
 | 
					    xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(wsr_ibreakenable)(uint32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t change = v ^ env->sregs[IBREAKENABLE];
 | 
				
			||||||
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < env->config->nibreak; ++i) {
 | 
				
			||||||
 | 
					        if (change & (1 << i)) {
 | 
				
			||||||
 | 
					            tb_invalidate_phys_page_range(
 | 
				
			||||||
 | 
					                    env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
 | 
				
			||||||
 | 
					        tb_invalidate_phys_page_range(
 | 
				
			||||||
 | 
					                env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
 | 
				
			||||||
 | 
					        tb_invalidate_phys_page_range(v, v + 1, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    env->sregs[IBREAKA + i] = v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
 | 
				
			||||||
 | 
					    uint32_t mask = dbreakc | ~DBREAKC_MASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (env->cpu_watchpoint[i]) {
 | 
				
			||||||
 | 
					        cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dbreakc & DBREAKC_SB) {
 | 
				
			||||||
 | 
					        flags |= BP_MEM_WRITE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dbreakc & DBREAKC_LB) {
 | 
				
			||||||
 | 
					        flags |= BP_MEM_READ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /* contiguous mask after inversion is one less than some power of 2 */
 | 
				
			||||||
 | 
					    if ((~mask + 1) & ~mask) {
 | 
				
			||||||
 | 
					        qemu_log("DBREAKC mask is not contiguous: 0x%08x\n", dbreakc);
 | 
				
			||||||
 | 
					        /* cut mask after the first zero bit */
 | 
				
			||||||
 | 
					        mask = 0xffffffff << (32 - clo32(mask));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cpu_watchpoint_insert(env, dbreaka & mask, ~mask + 1,
 | 
				
			||||||
 | 
					            flags, &env->cpu_watchpoint[i])) {
 | 
				
			||||||
 | 
					        env->cpu_watchpoint[i] = NULL;
 | 
				
			||||||
 | 
					        qemu_log("Failed to set data breakpoint at 0x%08x/%d\n",
 | 
				
			||||||
 | 
					                dbreaka & mask, ~mask + 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(wsr_dbreaka)(uint32_t i, uint32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t dbreakc = env->sregs[DBREAKC + i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((dbreakc & DBREAKC_SB_LB) &&
 | 
				
			||||||
 | 
					            env->sregs[DBREAKA + i] != v) {
 | 
				
			||||||
 | 
					        set_dbreak(i, v, dbreakc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    env->sregs[DBREAKA + i] = v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HELPER(wsr_dbreakc)(uint32_t i, uint32_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ((env->sregs[DBREAKC + i] ^ v) & (DBREAKC_SB_LB | DBREAKC_MASK)) {
 | 
				
			||||||
 | 
					        if (v & DBREAKC_SB_LB) {
 | 
				
			||||||
 | 
					            set_dbreak(i, env->sregs[DBREAKA + i], v);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (env->cpu_watchpoint[i]) {
 | 
				
			||||||
 | 
					                cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
 | 
				
			||||||
 | 
					                env->cpu_watchpoint[i] = NULL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    env->sregs[DBREAKC + i] = v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -114,6 +114,7 @@
 | 
				
			|||||||
        [EXC_KERNEL] = XCHAL_KERNEL_VECTOR_VADDR, \
 | 
					        [EXC_KERNEL] = XCHAL_KERNEL_VECTOR_VADDR, \
 | 
				
			||||||
        [EXC_USER] = XCHAL_USER_VECTOR_VADDR, \
 | 
					        [EXC_USER] = XCHAL_USER_VECTOR_VADDR, \
 | 
				
			||||||
        [EXC_DOUBLE] = XCHAL_DOUBLEEXC_VECTOR_VADDR, \
 | 
					        [EXC_DOUBLE] = XCHAL_DOUBLEEXC_VECTOR_VADDR, \
 | 
				
			||||||
 | 
					        [EXC_DEBUG] = XCHAL_DEBUG_VECTOR_VADDR, \
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define INTERRUPT_VECTORS { \
 | 
					#define INTERRUPT_VECTORS { \
 | 
				
			||||||
@ -251,6 +252,8 @@
 | 
				
			|||||||
    .nextint = XCHAL_NUM_EXTINTERRUPTS, \
 | 
					    .nextint = XCHAL_NUM_EXTINTERRUPTS, \
 | 
				
			||||||
    .extint = EXTINTS
 | 
					    .extint = EXTINTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if XCHAL_HAVE_PTP_MMU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TLB_TEMPLATE(ways, refill_way_size, way56) { \
 | 
					#define TLB_TEMPLATE(ways, refill_way_size, way56) { \
 | 
				
			||||||
        .nways = ways, \
 | 
					        .nways = ways, \
 | 
				
			||||||
        .way_size = { \
 | 
					        .way_size = { \
 | 
				
			||||||
@ -268,11 +271,23 @@
 | 
				
			|||||||
#define DTLB(varway56) \
 | 
					#define DTLB(varway56) \
 | 
				
			||||||
    TLB_TEMPLATE(10, 1 << XCHAL_DTLB_ARF_ENTRIES_LOG2, varway56)
 | 
					    TLB_TEMPLATE(10, 1 << XCHAL_DTLB_ARF_ENTRIES_LOG2, varway56)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if XCHAL_HAVE_PTP_MMU
 | 
					 | 
				
			||||||
#define TLB_SECTION \
 | 
					#define TLB_SECTION \
 | 
				
			||||||
    .itlb = ITLB(XCHAL_HAVE_SPANNING_WAY), \
 | 
					    .itlb = ITLB(XCHAL_HAVE_SPANNING_WAY), \
 | 
				
			||||||
    .dtlb = DTLB(XCHAL_HAVE_SPANNING_WAY)
 | 
					    .dtlb = DTLB(XCHAL_HAVE_SPANNING_WAY)
 | 
				
			||||||
#else
 | 
					
 | 
				
			||||||
 | 
					#elif XCHAL_HAVE_XLT_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TLB_TEMPLATE { \
 | 
				
			||||||
 | 
					        .nways = 1, \
 | 
				
			||||||
 | 
					        .way_size = { \
 | 
				
			||||||
 | 
					            8, \
 | 
				
			||||||
 | 
					        } \
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TLB_SECTION \
 | 
				
			||||||
 | 
					    .itlb = TLB_TEMPLATE, \
 | 
				
			||||||
 | 
					    .dtlb = TLB_TEMPLATE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if (defined(TARGET_WORDS_BIGENDIAN) != 0) == (XCHAL_HAVE_BE != 0)
 | 
					#if (defined(TARGET_WORDS_BIGENDIAN) != 0) == (XCHAL_HAVE_BE != 0)
 | 
				
			||||||
@ -288,6 +303,10 @@
 | 
				
			|||||||
#define REGISTER_CORE(core)
 | 
					#define REGISTER_CORE(core)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEBUG_SECTION \
 | 
				
			||||||
 | 
					    .debug_level = XCHAL_DEBUGLEVEL, \
 | 
				
			||||||
 | 
					    .nibreak = XCHAL_NUM_IBREAK, \
 | 
				
			||||||
 | 
					    .ndbreak = XCHAL_NUM_DBREAK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 2
 | 
					#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 2
 | 
				
			||||||
#define XCHAL_INTLEVEL2_VECTOR_VADDR 0
 | 
					#define XCHAL_INTLEVEL2_VECTOR_VADDR 0
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,10 @@ typedef struct DisasContext {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint32_t ccount_delta;
 | 
					    uint32_t ccount_delta;
 | 
				
			||||||
    unsigned used_window;
 | 
					    unsigned used_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool debug;
 | 
				
			||||||
 | 
					    bool icount;
 | 
				
			||||||
 | 
					    TCGv_i32 next_icount;
 | 
				
			||||||
} DisasContext;
 | 
					} DisasContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static TCGv_ptr cpu_env;
 | 
					static TCGv_ptr cpu_env;
 | 
				
			||||||
@ -91,6 +95,13 @@ static const char * const sregnames[256] = {
 | 
				
			|||||||
    [RASID] = "RASID",
 | 
					    [RASID] = "RASID",
 | 
				
			||||||
    [ITLBCFG] = "ITLBCFG",
 | 
					    [ITLBCFG] = "ITLBCFG",
 | 
				
			||||||
    [DTLBCFG] = "DTLBCFG",
 | 
					    [DTLBCFG] = "DTLBCFG",
 | 
				
			||||||
 | 
					    [IBREAKENABLE] = "IBREAKENABLE",
 | 
				
			||||||
 | 
					    [IBREAKA] = "IBREAKA0",
 | 
				
			||||||
 | 
					    [IBREAKA + 1] = "IBREAKA1",
 | 
				
			||||||
 | 
					    [DBREAKA] = "DBREAKA0",
 | 
				
			||||||
 | 
					    [DBREAKA + 1] = "DBREAKA1",
 | 
				
			||||||
 | 
					    [DBREAKC] = "DBREAKC0",
 | 
				
			||||||
 | 
					    [DBREAKC + 1] = "DBREAKC1",
 | 
				
			||||||
    [EPC1] = "EPC1",
 | 
					    [EPC1] = "EPC1",
 | 
				
			||||||
    [EPC1 + 1] = "EPC2",
 | 
					    [EPC1 + 1] = "EPC2",
 | 
				
			||||||
    [EPC1 + 2] = "EPC3",
 | 
					    [EPC1 + 2] = "EPC3",
 | 
				
			||||||
@ -119,8 +130,11 @@ static const char * const sregnames[256] = {
 | 
				
			|||||||
    [PS] = "PS",
 | 
					    [PS] = "PS",
 | 
				
			||||||
    [VECBASE] = "VECBASE",
 | 
					    [VECBASE] = "VECBASE",
 | 
				
			||||||
    [EXCCAUSE] = "EXCCAUSE",
 | 
					    [EXCCAUSE] = "EXCCAUSE",
 | 
				
			||||||
 | 
					    [DEBUGCAUSE] = "DEBUGCAUSE",
 | 
				
			||||||
    [CCOUNT] = "CCOUNT",
 | 
					    [CCOUNT] = "CCOUNT",
 | 
				
			||||||
    [PRID] = "PRID",
 | 
					    [PRID] = "PRID",
 | 
				
			||||||
 | 
					    [ICOUNT] = "ICOUNT",
 | 
				
			||||||
 | 
					    [ICOUNTLEVEL] = "ICOUNTLEVEL",
 | 
				
			||||||
    [EXCVADDR] = "EXCVADDR",
 | 
					    [EXCVADDR] = "EXCVADDR",
 | 
				
			||||||
    [CCOMPARE] = "CCOMPARE0",
 | 
					    [CCOMPARE] = "CCOMPARE0",
 | 
				
			||||||
    [CCOMPARE + 1] = "CCOMPARE1",
 | 
					    [CCOMPARE + 1] = "CCOMPARE1",
 | 
				
			||||||
@ -283,6 +297,19 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
 | 
				
			|||||||
    tcg_temp_free(tcause);
 | 
					    tcg_temp_free(tcause);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_debug_exception(DisasContext *dc, uint32_t cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TCGv_i32 tpc = tcg_const_i32(dc->pc);
 | 
				
			||||||
 | 
					    TCGv_i32 tcause = tcg_const_i32(cause);
 | 
				
			||||||
 | 
					    gen_advance_ccount(dc);
 | 
				
			||||||
 | 
					    gen_helper_debug_exception(tpc, tcause);
 | 
				
			||||||
 | 
					    tcg_temp_free(tpc);
 | 
				
			||||||
 | 
					    tcg_temp_free(tcause);
 | 
				
			||||||
 | 
					    if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
 | 
				
			||||||
 | 
					        dc->is_jmp = DISAS_UPDATE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_check_privilege(DisasContext *dc)
 | 
					static void gen_check_privilege(DisasContext *dc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (dc->cring) {
 | 
					    if (dc->cring) {
 | 
				
			||||||
@ -294,10 +321,13 @@ static void gen_check_privilege(DisasContext *dc)
 | 
				
			|||||||
static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 | 
					static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tcg_gen_mov_i32(cpu_pc, dest);
 | 
					    tcg_gen_mov_i32(cpu_pc, dest);
 | 
				
			||||||
 | 
					    gen_advance_ccount(dc);
 | 
				
			||||||
 | 
					    if (dc->icount) {
 | 
				
			||||||
 | 
					        tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (dc->singlestep_enabled) {
 | 
					    if (dc->singlestep_enabled) {
 | 
				
			||||||
        gen_exception(dc, EXCP_DEBUG);
 | 
					        gen_exception(dc, EXCP_DEBUG);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gen_advance_ccount(dc);
 | 
					 | 
				
			||||||
        if (slot >= 0) {
 | 
					        if (slot >= 0) {
 | 
				
			||||||
            tcg_gen_goto_tb(slot);
 | 
					            tcg_gen_goto_tb(slot);
 | 
				
			||||||
            tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
 | 
					            tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
 | 
				
			||||||
@ -492,6 +522,46 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			|||||||
    tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
 | 
					    tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gen_helper_wsr_ibreakenable(v);
 | 
				
			||||||
 | 
					    gen_jumpi_check_loop_end(dc, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned id = sr - IBREAKA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (id < dc->config->nibreak) {
 | 
				
			||||||
 | 
					        TCGv_i32 tmp = tcg_const_i32(id);
 | 
				
			||||||
 | 
					        gen_helper_wsr_ibreaka(tmp, v);
 | 
				
			||||||
 | 
					        tcg_temp_free(tmp);
 | 
				
			||||||
 | 
					        gen_jumpi_check_loop_end(dc, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned id = sr - DBREAKA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (id < dc->config->ndbreak) {
 | 
				
			||||||
 | 
					        TCGv_i32 tmp = tcg_const_i32(id);
 | 
				
			||||||
 | 
					        gen_helper_wsr_dbreaka(tmp, v);
 | 
				
			||||||
 | 
					        tcg_temp_free(tmp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned id = sr - DBREAKC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (id < dc->config->ndbreak) {
 | 
				
			||||||
 | 
					        TCGv_i32 tmp = tcg_const_i32(id);
 | 
				
			||||||
 | 
					        gen_helper_wsr_dbreakc(tmp, v);
 | 
				
			||||||
 | 
					        tcg_temp_free(tmp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
					static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tcg_gen_andi_i32(cpu_SR[sr], v,
 | 
					    tcg_gen_andi_i32(cpu_SR[sr], v,
 | 
				
			||||||
@ -535,10 +605,30 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			|||||||
    gen_jumpi_check_loop_end(dc, -1);
 | 
					    gen_jumpi_check_loop_end(dc, -1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
					static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (dc->icount) {
 | 
				
			||||||
 | 
					        tcg_gen_mov_i32(dc->next_icount, v);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tcg_gen_mov_i32(cpu_SR[sr], v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
 | 
				
			||||||
 | 
					    /* This can change tb->flags, so exit tb */
 | 
				
			||||||
 | 
					    gen_jumpi_check_loop_end(dc, -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
					static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t id = sr - CCOMPARE;
 | 
					    uint32_t id = sr - CCOMPARE;
 | 
				
			||||||
@ -567,11 +657,21 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
 | 
				
			|||||||
        [RASID] = gen_wsr_rasid,
 | 
					        [RASID] = gen_wsr_rasid,
 | 
				
			||||||
        [ITLBCFG] = gen_wsr_tlbcfg,
 | 
					        [ITLBCFG] = gen_wsr_tlbcfg,
 | 
				
			||||||
        [DTLBCFG] = gen_wsr_tlbcfg,
 | 
					        [DTLBCFG] = gen_wsr_tlbcfg,
 | 
				
			||||||
 | 
					        [IBREAKENABLE] = gen_wsr_ibreakenable,
 | 
				
			||||||
 | 
					        [IBREAKA] = gen_wsr_ibreaka,
 | 
				
			||||||
 | 
					        [IBREAKA + 1] = gen_wsr_ibreaka,
 | 
				
			||||||
 | 
					        [DBREAKA] = gen_wsr_dbreaka,
 | 
				
			||||||
 | 
					        [DBREAKA + 1] = gen_wsr_dbreaka,
 | 
				
			||||||
 | 
					        [DBREAKC] = gen_wsr_dbreakc,
 | 
				
			||||||
 | 
					        [DBREAKC + 1] = gen_wsr_dbreakc,
 | 
				
			||||||
        [INTSET] = gen_wsr_intset,
 | 
					        [INTSET] = gen_wsr_intset,
 | 
				
			||||||
        [INTCLEAR] = gen_wsr_intclear,
 | 
					        [INTCLEAR] = gen_wsr_intclear,
 | 
				
			||||||
        [INTENABLE] = gen_wsr_intenable,
 | 
					        [INTENABLE] = gen_wsr_intenable,
 | 
				
			||||||
        [PS] = gen_wsr_ps,
 | 
					        [PS] = gen_wsr_ps,
 | 
				
			||||||
 | 
					        [DEBUGCAUSE] = gen_wsr_debugcause,
 | 
				
			||||||
        [PRID] = gen_wsr_prid,
 | 
					        [PRID] = gen_wsr_prid,
 | 
				
			||||||
 | 
					        [ICOUNT] = gen_wsr_icount,
 | 
				
			||||||
 | 
					        [ICOUNTLEVEL] = gen_wsr_icountlevel,
 | 
				
			||||||
        [CCOMPARE] = gen_wsr_ccompare,
 | 
					        [CCOMPARE] = gen_wsr_ccompare,
 | 
				
			||||||
        [CCOMPARE + 1] = gen_wsr_ccompare,
 | 
					        [CCOMPARE + 1] = gen_wsr_ccompare,
 | 
				
			||||||
        [CCOMPARE + 2] = gen_wsr_ccompare,
 | 
					        [CCOMPARE + 2] = gen_wsr_ccompare,
 | 
				
			||||||
@ -749,7 +849,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint8_t b0 = ldub_code(dc->pc);
 | 
					    uint8_t b0 = ldub_code(dc->pc);
 | 
				
			||||||
    uint8_t b1 = ldub_code(dc->pc + 1);
 | 
					    uint8_t b1 = ldub_code(dc->pc + 1);
 | 
				
			||||||
    uint8_t b2 = ldub_code(dc->pc + 2);
 | 
					    uint8_t b2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static const uint32_t B4CONST[] = {
 | 
					    static const uint32_t B4CONST[] = {
 | 
				
			||||||
        0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
 | 
					        0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
 | 
				
			||||||
@ -764,6 +864,7 @@ static void disas_xtensa_insn(DisasContext *dc)
 | 
				
			|||||||
        HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
 | 
					        HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        dc->next_pc = dc->pc + 3;
 | 
					        dc->next_pc = dc->pc + 3;
 | 
				
			||||||
 | 
					        b2 = ldub_code(dc->pc + 2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (OP0) {
 | 
					    switch (OP0) {
 | 
				
			||||||
@ -968,8 +1069,10 @@ static void disas_xtensa_insn(DisasContext *dc)
 | 
				
			|||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case 4: /*BREAKx*/
 | 
					                case 4: /*BREAKx*/
 | 
				
			||||||
                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
 | 
					                    HAS_OPTION(XTENSA_OPTION_DEBUG);
 | 
				
			||||||
                    TBD();
 | 
					                    if (dc->debug) {
 | 
				
			||||||
 | 
					                        gen_debug_exception(dc, DEBUGCAUSE_BI);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case 5: /*SYSCALLx*/
 | 
					                case 5: /*SYSCALLx*/
 | 
				
			||||||
@ -2349,7 +2452,10 @@ static void disas_xtensa_insn(DisasContext *dc)
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case 2: /*BREAK.Nn*/
 | 
					            case 2: /*BREAK.Nn*/
 | 
				
			||||||
                TBD();
 | 
					                HAS_OPTION(XTENSA_OPTION_DEBUG);
 | 
				
			||||||
 | 
					                if (dc->debug) {
 | 
				
			||||||
 | 
					                    gen_debug_exception(dc, DEBUGCAUSE_BN);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case 3: /*NOP.Nn*/
 | 
					            case 3: /*NOP.Nn*/
 | 
				
			||||||
@ -2402,6 +2508,19 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gen_ibreak_check(CPUState *env, DisasContext *dc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < dc->config->nibreak; ++i) {
 | 
				
			||||||
 | 
					        if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
 | 
				
			||||||
 | 
					                env->sregs[IBREAKA + i] == dc->pc) {
 | 
				
			||||||
 | 
					            gen_debug_exception(dc, DEBUGCAUSE_IB);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_intermediate_code_internal(
 | 
					static void gen_intermediate_code_internal(
 | 
				
			||||||
        CPUState *env, TranslationBlock *tb, int search_pc)
 | 
					        CPUState *env, TranslationBlock *tb, int search_pc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -2428,10 +2547,15 @@ static void gen_intermediate_code_internal(
 | 
				
			|||||||
    dc.lend = env->sregs[LEND];
 | 
					    dc.lend = env->sregs[LEND];
 | 
				
			||||||
    dc.is_jmp = DISAS_NEXT;
 | 
					    dc.is_jmp = DISAS_NEXT;
 | 
				
			||||||
    dc.ccount_delta = 0;
 | 
					    dc.ccount_delta = 0;
 | 
				
			||||||
 | 
					    dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
 | 
				
			||||||
 | 
					    dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init_litbase(&dc);
 | 
					    init_litbase(&dc);
 | 
				
			||||||
    init_sar_tracker(&dc);
 | 
					    init_sar_tracker(&dc);
 | 
				
			||||||
    reset_used_window(&dc);
 | 
					    reset_used_window(&dc);
 | 
				
			||||||
 | 
					    if (dc.icount) {
 | 
				
			||||||
 | 
					        dc.next_icount = tcg_temp_local_new_i32();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gen_icount_start();
 | 
					    gen_icount_start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2467,8 +2591,27 @@ static void gen_intermediate_code_internal(
 | 
				
			|||||||
            gen_io_start();
 | 
					            gen_io_start();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dc.icount) {
 | 
				
			||||||
 | 
					            int label = gen_new_label();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
 | 
				
			||||||
 | 
					            tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
 | 
				
			||||||
 | 
					            tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
 | 
				
			||||||
 | 
					            if (dc.debug) {
 | 
				
			||||||
 | 
					                gen_debug_exception(&dc, DEBUGCAUSE_IC);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            gen_set_label(label);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (dc.debug) {
 | 
				
			||||||
 | 
					            gen_ibreak_check(env, &dc);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        disas_xtensa_insn(&dc);
 | 
					        disas_xtensa_insn(&dc);
 | 
				
			||||||
        ++insn_count;
 | 
					        ++insn_count;
 | 
				
			||||||
 | 
					        if (dc.icount) {
 | 
				
			||||||
 | 
					            tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (env->singlestep_enabled) {
 | 
					        if (env->singlestep_enabled) {
 | 
				
			||||||
            tcg_gen_movi_i32(cpu_pc, dc.pc);
 | 
					            tcg_gen_movi_i32(cpu_pc, dc.pc);
 | 
				
			||||||
            gen_exception(&dc, EXCP_DEBUG);
 | 
					            gen_exception(&dc, EXCP_DEBUG);
 | 
				
			||||||
@ -2481,6 +2624,9 @@ static void gen_intermediate_code_internal(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    reset_litbase(&dc);
 | 
					    reset_litbase(&dc);
 | 
				
			||||||
    reset_sar_tracker(&dc);
 | 
					    reset_sar_tracker(&dc);
 | 
				
			||||||
 | 
					    if (dc.icount) {
 | 
				
			||||||
 | 
					        tcg_temp_free(dc.next_icount);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (tb->cflags & CF_LAST_IO) {
 | 
					    if (tb->cflags & CF_LAST_IO) {
 | 
				
			||||||
        gen_io_end();
 | 
					        gen_io_end();
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ CRT        = crt.o vectors.o
 | 
				
			|||||||
TESTCASES += test_b.tst
 | 
					TESTCASES += test_b.tst
 | 
				
			||||||
TESTCASES += test_bi.tst
 | 
					TESTCASES += test_bi.tst
 | 
				
			||||||
#TESTCASES += test_boolean.tst
 | 
					#TESTCASES += test_boolean.tst
 | 
				
			||||||
 | 
					TESTCASES += test_break.tst
 | 
				
			||||||
TESTCASES += test_bz.tst
 | 
					TESTCASES += test_bz.tst
 | 
				
			||||||
TESTCASES += test_clamps.tst
 | 
					TESTCASES += test_clamps.tst
 | 
				
			||||||
TESTCASES += test_fail.tst
 | 
					TESTCASES += test_fail.tst
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										223
									
								
								tests/tcg/xtensa/test_break.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								tests/tcg/xtensa/test_break.S
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,223 @@
 | 
				
			|||||||
 | 
					.include "macros.inc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define debug_level 6
 | 
				
			||||||
 | 
					#define debug_vector level6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_suite break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test break
 | 
				
			||||||
 | 
					    set_vector debug_vector, 0
 | 
				
			||||||
 | 
					    rsil    a2, debug_level
 | 
				
			||||||
 | 
					    _break  0, 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    _break  0, 0
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    rsr     a2, ps
 | 
				
			||||||
 | 
					    movi    a3, 0x1f
 | 
				
			||||||
 | 
					    and     a2, a2, a3
 | 
				
			||||||
 | 
					    movi    a3, 0x10 | debug_level
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, epc6
 | 
				
			||||||
 | 
					    movi    a3, 1b
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x8
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test breakn
 | 
				
			||||||
 | 
					    set_vector debug_vector, 0
 | 
				
			||||||
 | 
					    rsil    a2, debug_level
 | 
				
			||||||
 | 
					    _break.n  0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    _break.n  0
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    rsr     a2, ps
 | 
				
			||||||
 | 
					    movi    a3, 0x1f
 | 
				
			||||||
 | 
					    and     a2, a2, a3
 | 
				
			||||||
 | 
					    movi    a3, 0x10 | debug_level
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, epc6
 | 
				
			||||||
 | 
					    movi    a3, 1b
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x10
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test ibreak
 | 
				
			||||||
 | 
					    set_vector debug_vector, 0
 | 
				
			||||||
 | 
					    rsil    a2, debug_level
 | 
				
			||||||
 | 
					    movi    a2, 1f
 | 
				
			||||||
 | 
					    wsr     a2, ibreaka0
 | 
				
			||||||
 | 
					    movi    a2, 1
 | 
				
			||||||
 | 
					    wsr     a2, ibreakenable
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					    movi    a2, 1f
 | 
				
			||||||
 | 
					    wsr     a2, ibreaka0
 | 
				
			||||||
 | 
					    movi    a2, 0
 | 
				
			||||||
 | 
					    wsr     a2, ibreakenable
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    movi    a2, 1f
 | 
				
			||||||
 | 
					    wsr     a2, ibreaka0
 | 
				
			||||||
 | 
					    movi    a2, 1
 | 
				
			||||||
 | 
					    wsr     a2, ibreakenable
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    rsr     a2, ps
 | 
				
			||||||
 | 
					    movi    a3, 0x1f
 | 
				
			||||||
 | 
					    and     a2, a2, a3
 | 
				
			||||||
 | 
					    movi    a3, 0x10 | debug_level
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, epc6
 | 
				
			||||||
 | 
					    movi    a3, 1b
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x2
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test ibreak_priority
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					    movi    a2, 1f
 | 
				
			||||||
 | 
					    wsr     a2, ibreaka0
 | 
				
			||||||
 | 
					    movi    a2, 1
 | 
				
			||||||
 | 
					    wsr     a2, ibreakenable
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    break   0, 0
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x2
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test icount
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					    movi    a2, -2
 | 
				
			||||||
 | 
					    wsr     a2, icount
 | 
				
			||||||
 | 
					    movi    a2, 1
 | 
				
			||||||
 | 
					    wsr     a2, icountlevel
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					    rsil    a2, 0
 | 
				
			||||||
 | 
					    nop
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    break   0, 0
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    movi    a2, 0
 | 
				
			||||||
 | 
					    wsr     a2, icountlevel
 | 
				
			||||||
 | 
					    rsr     a2, epc6
 | 
				
			||||||
 | 
					    movi    a3, 1b
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x1
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.macro check_dbreak dr
 | 
				
			||||||
 | 
					    rsr     a2, epc6
 | 
				
			||||||
 | 
					    movi    a3, 1b
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    rsr     a2, debugcause
 | 
				
			||||||
 | 
					    movi    a3, 0x4 | (\dr << 8)
 | 
				
			||||||
 | 
					    assert  eq, a2, a3
 | 
				
			||||||
 | 
					    movi    a2, 0
 | 
				
			||||||
 | 
					    wsr     a2, dbreakc\dr
 | 
				
			||||||
 | 
					.endm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.macro dbreak_test dr, ctl, break, access, op
 | 
				
			||||||
 | 
					    set_vector debug_vector, 2f
 | 
				
			||||||
 | 
					    rsil    a2, debug_level - 1
 | 
				
			||||||
 | 
					    movi    a2, \ctl
 | 
				
			||||||
 | 
					    wsr     a2, dbreakc\dr
 | 
				
			||||||
 | 
					    movi    a2, \break
 | 
				
			||||||
 | 
					    wsr     a2, dbreaka\dr
 | 
				
			||||||
 | 
					    movi    a2, \access
 | 
				
			||||||
 | 
					    isync
 | 
				
			||||||
 | 
					1:
 | 
				
			||||||
 | 
					    \op     a3, a2, 0
 | 
				
			||||||
 | 
					    test_fail
 | 
				
			||||||
 | 
					2:
 | 
				
			||||||
 | 
					    check_dbreak \dr
 | 
				
			||||||
 | 
					    reset_ps
 | 
				
			||||||
 | 
					.endm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test dbreak_exact
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x4000003f, 0xd000007f, 0xd000007f, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007e, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007c, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x8000003f, 0xd000007f, 0xd000007f, s8i
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007e, s16i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s32i
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test dbreak_overlap
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x4000003f, 0xd000007d, 0xd000007c, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x4000003f, 0xd000007d, 0xd000007c, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x4000003e, 0xd000007e, 0xd000007f, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007c, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007d, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x4000003c, 0xd000007c, 0xd000007c, l16ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007b, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x40000038, 0xd0000078, 0xd000007a, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007c, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000075, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000030, 0xd0000070, 0xd0000076, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000078, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000020, 0xd0000060, 0xd000006f, l8ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x40000020, 0xd0000060, 0xd0000070, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000020, 0xd0000060, 0xd0000074, l32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x8000003f, 0xd000007d, 0xd000007c, s16i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x8000003f, 0xd000007d, 0xd000007c, s32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007f, s8i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x8000003e, 0xd000007e, 0xd000007c, s32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x8000003c, 0xd000007c, 0xd000007d, s8i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s16i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007b, s8i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x80000038, 0xd0000078, 0xd000007a, s16i
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007c, s32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000075, s8i
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x80000030, 0xd0000070, 0xd0000076, s16i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000078, s32i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x80000020, 0xd0000060, 0xd000006f, s8i
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x80000020, 0xd0000060, 0xd0000070, s16i
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x80000020, 0xd0000060, 0xd0000074, s32i
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test dbreak_invalid
 | 
				
			||||||
 | 
					    dbreak_test 0, 0x40000030, 0xd0000071, 0xd0000070, l16ui
 | 
				
			||||||
 | 
					    dbreak_test 1, 0x40000035, 0xd0000072, 0xd0000070, l32i
 | 
				
			||||||
 | 
					test_end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_suite_end
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user