• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

コミットメタ情報

リビジョンba4443e1f3f8e5f98fd91d9b977bb4ff61d78028 (tree)
日時2018-12-12 14:23:32
作者Yoshinori Sato <ysato@user...>
コミッターYoshinori Sato

ログメッセージ

fix interrupt handling

変更サマリ

差分

--- a/hw/intc/rx_icu.c
+++ b/hw/intc/rx_icu.c
@@ -14,13 +14,33 @@
1414 #include "hw/intc/rx_icu.h"
1515 #include "qemu/error-report.h"
1616
17+#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n)
18+
19+
20+static qemu_irq* rxicu_pin(RXICUState *icu, int n_IRQ)
21+{
22+ if ((icu->fir & 0x8000) && (icu->fir & 0xff) == n_IRQ)
23+ return &icu->_fir;
24+ else
25+ return &icu->_irq;
26+}
27+
28+static void rxicu_request(RXICUState *icu, int n_IRQ)
29+{
30+ int enable;
31+
32+ enable = icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7));
33+ if (enable != 0 && icu->req_irq < 0) {
34+ qemu_set_irq(*rxicu_pin(icu, n_IRQ), 0x1000 | request(icu, n_IRQ));
35+ icu->req_irq = n_IRQ;
36+ }
37+}
38+
1739 static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
1840 {
1941 RXICUState *icu = opaque;
2042 struct IRQSource *src;
21- int req;
2243 int issue;
23- qemu_irq *ir;
2444
2545 if (n_IRQ >= 256) {
2646 error_report("%s: IRQ %d out of range", __func__, n_IRQ);
@@ -28,14 +48,8 @@ static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
2848 }
2949
3050 src = &icu->src[n_IRQ];
31- if ((icu->fir & 0x8000) && (icu->fir & 0xff) == n_IRQ) {
32- ir = &icu->_fir;
33- req = 0;
34- } else {
35- ir = &icu->_irq;
36- req = icu->ipr[icu->map[n_IRQ]] << 8 | n_IRQ;
37- }
3851
52+ level = (level != 0);
3953 switch (src->sense) {
4054 case TRG_LEVEL:
4155 /* level-sensitive irq */
@@ -55,13 +69,43 @@ static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
5569 src->level = level;
5670 break;
5771 }
58- if (issue) {
59- qemu_set_irq(*ir, 0x1000 | req);
60- icu->ir[n_IRQ] = 1;
61- } else if (src->sense == TRG_LEVEL) {
62- qemu_set_irq(*ir, req);
72+ if (issue == 0 && src->sense == TRG_LEVEL) {
6373 icu->ir[n_IRQ] = 0;
74+ if (icu->req_irq == n_IRQ) {
75+ qemu_set_irq(*rxicu_pin(icu, n_IRQ), request(icu, n_IRQ));
76+ icu->req_irq = -1;
77+ }
78+ return;
6479 }
80+ if (issue)
81+ rxicu_request(icu, n_IRQ);
82+}
83+
84+static void rxicu_ack_irq(void *opaque, int no, int level)
85+{
86+ RXICUState *icu = opaque;
87+ int i;
88+ int n_IRQ;
89+ int max_pri;
90+
91+ if (icu->req_irq < 0)
92+ return;
93+ if (icu->src[icu->req_irq].sense != TRG_LEVEL)
94+ icu->ir[icu->req_irq] = 0;
95+ icu->req_irq = -1;
96+
97+ max_pri = 0;
98+ n_IRQ = -1;
99+ for (i = 0; i < 256; i++) {
100+ if (icu->ir[i]) {
101+ if (max_pri < icu->ipr[icu->map[i]]) {
102+ n_IRQ = i;
103+ max_pri = icu->ipr[icu->map[i]];
104+ }
105+ }
106+ }
107+ if (n_IRQ >= 0)
108+ rxicu_request(icu, n_IRQ);
65109 }
66110
67111 static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size)
@@ -123,13 +167,8 @@ static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
123167 if (!error) {
124168 switch (offset) {
125169 case 0x000 ... 0x0ff:
126- if (icu->src[reg].sense != TRG_LEVEL && val == 0) {
170+ if (icu->src[reg].sense != TRG_LEVEL && val == 0)
127171 icu->ir[reg] = 0;
128- if ((icu->fir & 0xff) == reg)
129- qemu_set_irq(icu->_fir, 0);
130- else
131- qemu_set_irq(icu->_irq, reg);
132- }
133172 break;
134173 case 0x100 ... 0x1ff:
135174 icu->dtcer[reg] = val & 1;
@@ -195,6 +234,7 @@ static void rxicu_realize(DeviceState *dev, Error **errp)
195234 } else
196235 icu->src[i].sense = TRG_PEDGE;
197236 }
237+ icu->req_irq = -1;
198238 }
199239
200240 static void rxicu_init(Object *obj)
@@ -207,6 +247,7 @@ static void rxicu_init(Object *obj)
207247 sysbus_init_mmio(d, &icu->memory);
208248
209249 qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, 256);
250+ qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1);
210251 sysbus_init_irq(d, &icu->_irq);
211252 sysbus_init_irq(d, &icu->_fir);
212253 sysbus_init_irq(d, &icu->_swi);
--- a/hw/rx/rx62n.c
+++ b/hw/rx/rx62n.c
@@ -68,10 +68,6 @@ static RXICUState *register_icu(RX62NState *s)
6868
6969 icu = SYS_BUS_DEVICE(qdev_create(NULL, TYPE_RXICU));
7070 sysbus_mmio_map(icu, 0, 0x00087000);
71- sysbus_connect_irq(icu, RX_CPU_IRQ,
72- qdev_get_gpio_in(DEVICE(s->cpu), RX_CPU_IRQ));
73- sysbus_connect_irq(icu, RX_CPU_FIR,
74- qdev_get_gpio_in(DEVICE(s->cpu), RX_CPU_FIR));
7571 qdev_prop_set_string(DEVICE(icu), "icutype", "icua");
7672 qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", 256);
7773 for (i = 0; i < 256; i++) {
@@ -164,14 +160,15 @@ static void rx62n_realize(DeviceState *dev, Error **errp)
164160
165161 if (!s->kernel)
166162 rom_add_file_fixed(bios_name, 0xfff80000, 0);
167- else
168163
169164 object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
170165 if (err != NULL) {
171166 error_propagate(errp, err);
172167 return;
173168 }
169+
174170 s->icu = register_icu(s);
171+ s->cpu->env.ack = qdev_get_gpio_in_named(DEVICE(s->icu), "ack", 0);
175172 s->tmr[0] = register_tmr(s, 0);
176173 s->tmr[1] = register_tmr(s, 1);
177174 s->cmt[0] = register_cmt(s, 0);
--- a/include/hw/intc/rx_icu.h
+++ b/include/hw/intc/rx_icu.h
@@ -30,6 +30,7 @@ struct RXICUState {
3030 uint8_t nmier;
3131 uint8_t nmiclr;
3232 uint8_t nmicr;
33+ int req_irq;
3334 qemu_irq _irq;
3435 qemu_irq _fir;
3536 qemu_irq _swi;
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -120,7 +120,7 @@ typedef struct CPURXState {
120120 uint32_t in_sleep;
121121 uint32_t intlevel;
122122 uint32_t irq;
123- uint32_t int_insn_len;
123+ uint32_t sirq;
124124 float_status fp_status;
125125 uint32_t op_a1[12];
126126 uint32_t op_a2[12];
@@ -131,7 +131,7 @@ typedef struct CPURXState {
131131
132132 CPU_COMMON
133133
134- void *intc_handle;
134+ void *ack;
135135 } CPURXState;
136136
137137 /**
@@ -177,6 +177,7 @@ void rx_cpu_list(FILE *f, fprintf_function cpu_fprintf);
177177 void rx_load_image(RXCPU *cpu, const char *filename,
178178 uint32_t start, uint32_t size);
179179 void rx_cpu_pack_psw(CPURXState *env);
180+void rx_cpu_unpack_psw(CPURXState *env, int all);
180181
181182 #define cpu_signal_handler cpu_rx_signal_handler
182183 #define cpu_list rx_cpu_list
@@ -200,27 +201,6 @@ enum {
200201 ACCESS_INT = 0x20
201202 };
202203
203-static inline target_ulong cpu_read_psw(CPURXState *env)
204-{
205- return (env->psw_o << PSW_O) | (env->psw_s << PSW_S) |
206- (env->psw_z << PSW_Z) | (env->psw_c << PSW_C) |
207- (env->psw_u << PSW_U) | (env->psw_u << PSW_I) |
208- (env->psw_u << PSW_PM) | (env->psw_u << PSW_IPL);
209-}
210-
211-static inline void cpu_write_psw(CPURXState *env, target_ulong psw)
212-{
213- env->psw = psw;
214- env->psw_o = (psw >> PSW_O) & 1;
215- env->psw_s = (psw >> PSW_S) & 1;
216- env->psw_z = (psw >> PSW_Z) & 1;
217- env->psw_c = (psw >> PSW_C) & 1;
218- env->psw_i = (psw >> PSW_I) & 1;
219- env->psw_u = (psw >> PSW_U) & 1;
220- env->psw_pm = (psw >> PSW_PM) & 1;
221- env->psw_ipl = (psw >> PSW_IPL) & 4;
222-}
223-
224204 static inline void cpu_get_tb_cpu_state(CPURXState *env, target_ulong *pc,
225205 target_ulong *cs_base, uint32_t *flags)
226206 {
--- a/target/rx/helper.c
+++ b/target/rx/helper.c
@@ -210,24 +210,20 @@ void rx_cpu_do_interrupt(CPUState *cs)
210210 CPURXState *env = &cpu->env;
211211 int do_irq = cs->interrupt_request &
212212 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_SOFT | CPU_INTERRUPT_FIR);
213- int do_exp, irq_vector = -1;
214-
215- do_exp = cs->exception_index < 0x100;
213+ int irq_vector = -1;
216214
217215 env->in_sleep = 0;
218216
219- if (!do_irq) {
220- cs->interrupt_request = 0;
221- return ;
222- }
223217 if (do_irq & CPU_INTERRUPT_HARD) {
224218 irq_vector = env->irq;
225- if (irq_vector == -1 || env->psw_i == 0) {
219+ if (irq_vector == -1 ||
220+ (env->psw_i == 0 && !(do_irq & CPU_INTERRUPT_SOFT))) {
226221 return; /* masked */
227222 }
223+ cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
228224 }
229- if (do_irq & CPU_INTERRUPT_SOFT) {
230- irq_vector = env->irq;
225+ if (irq_vector == -1 && do_irq & CPU_INTERRUPT_SOFT) {
226+ irq_vector = env->sirq;
231227 cs->interrupt_request &= ~CPU_INTERRUPT_SOFT;
232228 }
233229
@@ -278,23 +274,24 @@ void rx_cpu_do_interrupt(CPUState *cs)
278274 env->bpc = env->pc;
279275 env->bpsw = env->psw;
280276 }
281- env->psw &= ~((1UL << PSW_PM) | (1UL << PSW_I) | (1UL << PSW_U));
282277 env->psw_pm = env->psw_i = env->psw_u = 0;
283278 env->regs[0] = env->isp;
284- if (do_irq & CPU_INTERRUPT_HARD)
285- env->psw_ipl = env->intlevel;
286-
287- if (do_exp) {
288- uint32_t vec = cs->exception_index;
289- env->pc = cpu_ldl_all(env, 0xffffffc0 + vec * 4);
290- return;
291- }
292-
293279 if (do_irq) {
294- if (do_irq & CPU_INTERRUPT_FIR)
280+ if (do_irq & CPU_INTERRUPT_FIR) {
295281 env->pc = env->fintv;
296- else
297- env->pc = cpu_ldl_all(env, env->intb + irq_vector * 4);
282+ env->psw_ipl = 15;
283+ cs->interrupt_request &= ~CPU_INTERRUPT_FIR;
284+ qemu_set_irq(env->ack, 0);
285+ return;
286+ } else if (do_irq & CPU_INTERRUPT_HARD) {
287+ env->psw_ipl = env->intlevel;
288+ qemu_set_irq(env->ack, 0);
289+ }
290+ env->pc = cpu_ldl_all(env, env->intb + irq_vector * 4);
291+ return;
292+ } else {
293+ uint32_t vec = cs->exception_index;
294+ env->pc = cpu_ldl_all(env, 0xffffffc0 + vec * 4);
298295 return;
299296 }
300297 }
@@ -306,11 +303,11 @@ bool rx_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
306303 if (((interrupt_request & CPU_INTERRUPT_HARD) &&
307304 (env->psw_i && (env->psw_ipl < env->intlevel))) |
308305 (interrupt_request & CPU_INTERRUPT_SOFT) ||
309- (env->psw_i && (interrupt_request & CPU_INTERRUPT_FIR))) {
306+ (env->psw_i && (interrupt_request & CPU_INTERRUPT_FIR) &&
307+ (env->psw_ipl < 15))) {
310308 rx_cpu_do_interrupt(cs);
311309 return true;
312310 }
313-
314311 return false;
315312 }
316313
@@ -365,8 +362,7 @@ void QEMU_NORETURN helper_rxint(CPURXState *env, uint32_t vec)
365362 CPUState *cs = CPU(rx_env_get_cpu(env));
366363
367364 cs->interrupt_request |= CPU_INTERRUPT_SOFT;
368- env->irq = vec;
369- printf("int r13=0x%08x, r15=0x%08x\n", env->regs[13], env->regs[15]);
365+ env->sirq = vec;
370366 raise_exception(env, 0x100, 0);
371367 }
372368
@@ -375,7 +371,7 @@ void QEMU_NORETURN helper_rxbrk(CPURXState *env)
375371 CPUState *cs = CPU(rx_env_get_cpu(env));
376372
377373 cs->interrupt_request |= CPU_INTERRUPT_SOFT;
378- env->irq = 0;
374+ env->sirq = 0;
379375 raise_exception(env, 0x100, 0);
380376 }
381377