Revision e62b5b13 target-cris/helper.c

b/target-cris/helper.c
28 28
#include "exec-all.h"
29 29
#include "host-utils.h"
30 30

  
31
#define D(x)
32

  
31 33
#if defined(CONFIG_USER_ONLY)
32 34

  
33 35
void do_interrupt (CPUState *env)
......
53 55

  
54 56
#else /* !CONFIG_USER_ONLY */
55 57

  
58

  
59
static void cris_shift_ccs(CPUState *env)
60
{
61
	uint32_t ccs;
62
	/* Apply the ccs shift.  */
63
	ccs = env->pregs[PR_CCS];
64
	ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
65
	env->pregs[PR_CCS] = ccs;
66
}
67

  
56 68
int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
57 69
                               int mmu_idx, int is_softmmu)
58 70
{
59 71
	struct cris_mmu_result_t res;
60 72
	int prot, miss;
73
	int r = -1;
61 74
	target_ulong phy;
62 75

  
76
	D(printf ("%s addr=%x pc=%x\n", __func__, address, env->pc));
63 77
	address &= TARGET_PAGE_MASK;
64 78
	prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
65 79
	miss = cris_mmu_translate(&res, env, address, rw, mmu_idx);
66 80
	if (miss)
67 81
	{
68
		/* handle the miss.  */
69
		phy = 0;
70
		env->exception_index = EXCP_MMU_MISS;
82
		env->exception_index = EXCP_MMU_FAULT;
83
		env->fault_vector = res.bf_vec;
84
		r = 1;
71 85
	}
72 86
	else
73 87
	{
74 88
		phy = res.phy;
89
		prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
90
		r = tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu);
75 91
	}
76
	return tlb_set_page(env, address, phy, prot, mmu_idx, is_softmmu);
77
}
78

  
79

  
80
static void cris_shift_ccs(CPUState *env)
81
{
82
	uint32_t ccs;
83
	/* Apply the ccs shift.  */
84
	ccs = env->pregs[PR_CCS];
85
	ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
86
	env->pregs[PR_CCS] = ccs;
92
	D(printf("%s returns %d irqreq=%x addr=%x ismmu=%d\n", 
93
			__func__, r, env->interrupt_request, 
94
			address, is_softmmu));
95
	return r;
87 96
}
88 97

  
89 98
void do_interrupt(CPUState *env)
90 99
{
91
	uint32_t ebp, isr;
92
	int irqnum;
93

  
94
	fflush(NULL);
100
	int ex_vec = -1;
95 101

  
96
#if 0
97
	printf ("exception index=%d interrupt_req=%d\n",
98
		env->exception_index,
99
		env->interrupt_request);
100
#endif
102
	D(fprintf (stderr, "exception index=%d interrupt_req=%d\n",
103
		 env->exception_index,
104
		 env->interrupt_request));
101 105

  
102 106
	switch (env->exception_index)
103 107
	{
104 108
		case EXCP_BREAK:
105
			irqnum = env->trapnr;
106
			ebp = env->pregs[PR_EBP];
107
			isr = ldl_code(ebp + irqnum * 4);
109
			/* These exceptions are genereated by the core itself.
110
			   ERP should point to the insn following the brk.  */
111
			ex_vec = env->trap_vector;
108 112
			env->pregs[PR_ERP] = env->pc + 2;
109
			env->pc = isr;
110

  
111
			cris_shift_ccs(env);
112

  
113 113
			break;
114
		case EXCP_MMU_MISS:
115
			irqnum = 4;
116
			ebp = env->pregs[PR_EBP];
117
			isr = ldl_code(ebp + irqnum * 4);
118
			env->pregs[PR_ERP] = env->pc;
119
			env->pc = isr;
120
			cris_shift_ccs(env);
114

  
115
		case EXCP_MMU_FAULT:
116
			/* ERP is already setup by translate-all.c through
117
			   re-translation of the aborted TB combined with 
118
			   pc searching.  */
119
			ex_vec = env->fault_vector;
121 120
			break;
122 121

  
123 122
		default:
......
125 124
			/* Maybe the irq was acked by sw before we got a
126 125
			   change to take it.  */
127 126
			if (env->interrupt_request & CPU_INTERRUPT_HARD) {
128
				if (!env->pending_interrupts)
127
				/* Vectors below 0x30 are internal
128
				   exceptions, i.e not interrupt requests
129
				   from the interrupt controller.  */
130
				if (env->interrupt_vector < 0x30)
129 131
					return;
132
				/* Is the core accepting interrupts?  */
130 133
				if (!(env->pregs[PR_CCS] & I_FLAG)) {
131 134
					return;
132 135
				}
133

  
134
				irqnum = 31 - clz32(env->pending_interrupts);
135
				irqnum += 0x30;
136
				ebp = env->pregs[PR_EBP];
137
				isr = ldl_code(ebp + irqnum * 4);
136
				/* The interrupt controller gives us the
137
				   vector.  */
138
				ex_vec = env->interrupt_vector;
139
				/* Normal interrupts are taken between
140
				   TB's.  env->pc is valid here.  */
138 141
				env->pregs[PR_ERP] = env->pc;
139
				env->pc = isr;
140

  
141
				cris_shift_ccs(env);
142
#if 0
143
				printf ("%s ebp=%x %x isr=%x %d"
144
					" ir=%x pending=%x\n",
145
					__func__,
146
					ebp, ebp + irqnum * 4,
147
					isr, env->exception_index,
148
					env->interrupt_request,
149
					env->pending_interrupts);
150
#endif
151 142
			}
152

  
153 143
		}
154 144
		break;
155 145
	}
146
	env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
147
	/* Apply the CRIS CCS shift.  */
148
	cris_shift_ccs(env);
149
	D(printf ("%s ebp=%x isr=%x vec=%x\n", __func__, ebp, isr, ex_vec));
156 150
}
157 151

  
158 152
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
......
163 157
	miss = cris_mmu_translate(&res, env, addr, 0, 0);
164 158
	if (!miss)
165 159
		phy = res.phy;
160
	D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
166 161
	return phy;
167 162
}
168 163
#endif

Also available in: Unified diff