]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/mn10300/dv-mn103int.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / sim / mn10300 / dv-mn103int.c
1 /* This file is part of the program GDB, the GNU debugger.
2
3 Copyright (C) 1998 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22
23 #include "sim-main.h"
24 #include "hw-main.h"
25 #include "sim-hw.h"
26
27 /* DEVICE
28
29
30 mn103int - mn103002 interrupt controller
31
32
33 DESCRIPTION
34
35
36 Implements the mn103002 interrupt controller described in the
37 mn103002 user guide.
38
39
40 PROPERTIES
41
42
43 reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
44
45 Specify the address of the ICR (total of 30 registers), IAGR and
46 EXTMD registers (within the parent bus).
47
48 The reg property value `0x34000100 0x7C 0x34000200 0x8 0x3400280
49 0x8' locates the interrupt controller at the addresses specified in
50 the mn103002 interrupt controller user guide.
51
52
53 PORTS
54
55
56 nmi (output)
57
58 Non-maskable interrupt output port. An event on this output ports
59 indicates a NMI request from the interrupt controller. The value
60 attached to the event should be ignored.
61
62
63 level (output)
64
65 Maskable interrupt level output port. An event on this output port
66 indicates a maskable interrupt request at the specified level. The
67 event value defines the level being requested.
68
69 The interrupt controller will generate an event on this port
70 whenever there is a change to the internal state of the interrupt
71 controller.
72
73
74 ack (input)
75
76 Signal from processor indicating that a maskable interrupt has been
77 accepted and the interrupt controller should latch the IAGR with
78 value of the current highest priority interrupting group.
79
80 The event value is the interrupt level being accepted by the
81 processor. It should be consistent with the most recent LEVEL sent
82 to the processor from the interrupt controller.
83
84
85 int[0..100] (input)
86
87 Level or edge triggered interrupt input port. Each of the 30
88 groups (0..30) can have up to 4 (0..3) interrupt inputs. The
89 interpretation of a port event/value is determined by the
90 configuration of the corresponding interrupt group.
91
92 For convenience, numerous aliases to these interrupt inputs are
93 provided.
94
95
96 BUGS
97
98
99 For edge triggered interrupts, the interrupt controller does not
100 differentiate between POSITIVE (rising) and NEGATIVE (falling)
101 edges. Instead any input port event is considered to be an
102 interrupt trigger.
103
104 For level sensitive interrupts, the interrupt controller ignores
105 active HIGH/LOW settings and instead always interprets a nonzero
106 port value as an interrupt assertion and a zero port value as a
107 negation.
108
109 */
110
111
112 /* The interrupt groups - numbered according to mn103002 convention */
113
114 enum mn103int_trigger {
115 ACTIVE_LOW,
116 ACTIVE_HIGH,
117 POSITIVE_EDGE,
118 NEGATIVE_EDGE,
119 };
120
121 enum mn103int_type {
122 NMI_GROUP,
123 LEVEL_GROUP,
124 };
125
126 struct mn103int_group {
127 int gid;
128 int level;
129 unsigned enable;
130 unsigned request;
131 unsigned input;
132 enum mn103int_trigger trigger;
133 enum mn103int_type type;
134 };
135
136 enum {
137 FIRST_NMI_GROUP = 0,
138 LAST_NMI_GROUP = 1,
139 FIRST_LEVEL_GROUP = 2,
140 LAST_LEVEL_GROUP = 30,
141 NR_GROUPS,
142 };
143
144 enum {
145 LOWEST_LEVEL = 7,
146 };
147
148 /* The interrupt controller register address blocks */
149
150 struct mn103int_block {
151 unsigned_word base;
152 unsigned_word bound;
153 };
154
155 enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
156
157
158 struct mn103int {
159 struct mn103int_block block[NR_BLOCKS];
160 struct mn103int_group group[NR_GROUPS];
161 unsigned interrupt_accepted_group;
162 };
163
164
165
166 /* output port ID's */
167
168 enum {
169 NMI_PORT,
170 LEVEL_PORT,
171 };
172
173
174 /* input port ID's */
175
176 enum {
177 G0_PORT = 0,
178 G1_PORT = 4,
179 G2_PORT = 8,
180 G3_PORT = 12,
181 G4_PORT = 16,
182 G5_PORT = 20,
183 G6_PORT = 24,
184 G7_PORT = 28,
185 G8_PORT = 32,
186 G9_PORT = 36,
187 G10_PORT = 40,
188 G11_PORT = 44,
189 G12_PORT = 48,
190 G13_PORT = 52,
191 G14_PORT = 56,
192 G15_PORT = 60,
193 G16_PORT = 64,
194 G17_PORT = 68,
195 G18_PORT = 72,
196 G19_PORT = 76,
197 G20_PORT = 80,
198 G21_PORT = 84,
199 G22_PORT = 88,
200 G23_PORT = 92,
201 IRQ0_PORT = G23_PORT,
202 G24_PORT = 96,
203 G25_PORT = 100,
204 G26_PORT = 104,
205 G27_PORT = 108,
206 IRQ4_PORT = G27_PORT,
207 G28_PORT = 112,
208 G29_PORT = 116,
209 G30_PORT = 120,
210 NR_G_PORTS = 124,
211 ACK_PORT,
212 };
213
214 static const struct hw_port_descriptor mn103int_ports[] = {
215
216 /* interrupt outputs */
217
218 { "nmi", NMI_PORT, 0, output_port, },
219 { "level", LEVEL_PORT, 0, output_port, },
220
221 /* interrupt ack (latch) input from cpu */
222
223 { "ack", ACK_PORT, 0, input_port, },
224
225 /* interrupt inputs (as names) */
226
227 { "nmirq", G0_PORT + 0, 0, input_port, },
228 { "watchdog", G0_PORT + 1, 0, input_port, },
229 { "syserr", G0_PORT + 2, 0, input_port, },
230
231 { "timer-0-underflow", G2_PORT, 0, input_port, },
232 { "timer-1-underflow", G3_PORT, 0, input_port, },
233 { "timer-2-underflow", G4_PORT, 0, input_port, },
234 { "timer-3-underflow", G5_PORT, 0, input_port, },
235 { "timer-4-underflow", G6_PORT, 0, input_port, },
236 { "timer-5-underflow", G7_PORT, 0, input_port, },
237 { "timer-6-underflow", G8_PORT, 0, input_port, },
238
239 { "timer-6-compare-a", G9_PORT, 0, input_port, },
240 { "timer-6-compare-b", G10_PORT, 0, input_port, },
241
242 { "dma-0-end", G12_PORT, 0, input_port, },
243 { "dma-1-end", G13_PORT, 0, input_port, },
244 { "dma-2-end", G14_PORT, 0, input_port, },
245 { "dma-3-end", G15_PORT, 0, input_port, },
246
247 { "serial-0-receive", G16_PORT, 0, input_port, },
248 { "serial-0-transmit", G17_PORT, 0, input_port, },
249
250 { "serial-1-receive", G18_PORT, 0, input_port, },
251 { "serial-1-transmit", G19_PORT, 0, input_port, },
252
253 { "serial-2-receive", G20_PORT, 0, input_port, },
254 { "serial-2-transmit", G21_PORT, 0, input_port, },
255
256 { "irq-0", G23_PORT, 0, input_port, },
257 { "irq-1", G24_PORT, 0, input_port, },
258 { "irq-2", G25_PORT, 0, input_port, },
259 { "irq-3", G26_PORT, 0, input_port, },
260 { "irq-4", G27_PORT, 0, input_port, },
261 { "irq-5", G28_PORT, 0, input_port, },
262 { "irq-6", G29_PORT, 0, input_port, },
263 { "irq-7", G30_PORT, 0, input_port, },
264
265 /* interrupt inputs (as generic numbers) */
266
267 { "int", 0, NR_G_PORTS, input_port, },
268
269 { NULL, },
270 };
271
272
273 /* Macros for extracting/restoring the various register bits */
274
275 #define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
276 #define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
277
278 #define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
279 #define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
280
281 #define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
282 #define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
283
284 #define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
285 #define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
286
287
288
289 /* Finish off the partially created hw device. Attach our local
290 callbacks. Wire up our port names etc */
291
292 static hw_io_read_buffer_method mn103int_io_read_buffer;
293 static hw_io_write_buffer_method mn103int_io_write_buffer;
294 static hw_port_event_method mn103int_port_event;
295 static hw_ioctl_method mn103int_ioctl;
296
297
298
299 static void
300 attach_mn103int_regs (struct hw *me,
301 struct mn103int *controller)
302 {
303 int i;
304 if (hw_find_property (me, "reg") == NULL)
305 hw_abort (me, "Missing \"reg\" property");
306 for (i = 0; i < NR_BLOCKS; i++)
307 {
308 unsigned_word attach_address;
309 int attach_space;
310 unsigned attach_size;
311 reg_property_spec reg;
312 if (!hw_find_reg_array_property (me, "reg", i, &reg))
313 hw_abort (me, "\"reg\" property must contain three addr/size entries");
314 hw_unit_address_to_attach_address (hw_parent (me),
315 &reg.address,
316 &attach_space,
317 &attach_address,
318 me);
319 controller->block[i].base = attach_address;
320 hw_unit_size_to_attach_size (hw_parent (me),
321 &reg.size,
322 &attach_size, me);
323 controller->block[i].bound = attach_address + (attach_size - 1);
324 hw_attach_address (hw_parent (me),
325 0,
326 attach_space, attach_address, attach_size,
327 me);
328 }
329 }
330
331 static void
332 mn103int_finish (struct hw *me)
333 {
334 int gid;
335 struct mn103int *controller;
336
337 controller = HW_ZALLOC (me, struct mn103int);
338 set_hw_data (me, controller);
339 set_hw_io_read_buffer (me, mn103int_io_read_buffer);
340 set_hw_io_write_buffer (me, mn103int_io_write_buffer);
341 set_hw_ports (me, mn103int_ports);
342 set_hw_port_event (me, mn103int_port_event);
343 me->to_ioctl = mn103int_ioctl;
344
345 /* Attach ourself to our parent bus */
346 attach_mn103int_regs (me, controller);
347
348 /* Initialize all the groups according to their default configuration */
349 for (gid = 0; gid < NR_GROUPS; gid++)
350 {
351 struct mn103int_group *group = &controller->group[gid];
352 group->trigger = NEGATIVE_EDGE;
353 group->gid = gid;
354 if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
355 {
356 group->enable = 0xf;
357 group->type = NMI_GROUP;
358 }
359 else if (FIRST_LEVEL_GROUP <= gid && gid <= LAST_LEVEL_GROUP)
360 {
361 group->enable = 0x0;
362 group->type = LEVEL_GROUP;
363 }
364 else
365 hw_abort (me, "internal error - unknown group id");
366 }
367 }
368
369
370
371 /* Perform the nasty work of figuring out which of the interrupt
372 groups should have its interrupt delivered. */
373
374 static int
375 find_highest_interrupt_group (struct hw *me,
376 struct mn103int *controller)
377 {
378 int gid;
379 int selected;
380
381 /* FIRST_NMI_GROUP (group zero) is used as a special default value
382 when searching for an interrupt group.*/
383 selected = FIRST_NMI_GROUP;
384 controller->group[FIRST_NMI_GROUP].level = 7;
385
386 for (gid = FIRST_LEVEL_GROUP; gid <= LAST_LEVEL_GROUP; gid++)
387 {
388 struct mn103int_group *group = &controller->group[gid];
389 if ((group->request & group->enable) != 0)
390 {
391 /* Remember, lower level, higher priority. */
392 if (group->level < controller->group[selected].level)
393 {
394 selected = gid;
395 }
396 }
397 }
398 return selected;
399 }
400
401
402 /* Notify the processor of an interrupt level update */
403
404 static void
405 push_interrupt_level (struct hw *me,
406 struct mn103int *controller)
407 {
408 int selected = find_highest_interrupt_group (me, controller);
409 int level = controller->group[selected].level;
410 HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
411 hw_port_event (me, LEVEL_PORT, level);
412 }
413
414
415 /* An event arrives on an interrupt port */
416
417 static void
418 mn103int_port_event (struct hw *me,
419 int my_port,
420 struct hw *source,
421 int source_port,
422 int level)
423 {
424 struct mn103int *controller = hw_data (me);
425
426 switch (my_port)
427 {
428
429 case ACK_PORT:
430 {
431 int selected = find_highest_interrupt_group (me, controller);
432 if (controller->group[selected].level != level)
433 hw_abort (me, "botched level synchronisation");
434 controller->interrupt_accepted_group = selected;
435 HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
436 level, selected));
437 break;
438 }
439
440 default:
441 {
442 int gid;
443 int iid;
444 struct mn103int_group *group;
445 unsigned interrupt;
446 if (my_port > NR_G_PORTS)
447 hw_abort (me, "Event on unknown port %d", my_port);
448
449 /* map the port onto an interrupt group */
450 gid = (my_port % NR_G_PORTS) / 4;
451 group = &controller->group[gid];
452 iid = (my_port % 4);
453 interrupt = 1 << iid;
454
455 /* update our cached input */
456 if (level)
457 group->input |= interrupt;
458 else
459 group->input &= ~interrupt;
460
461 /* update the request bits */
462 switch (group->trigger)
463 {
464 case ACTIVE_LOW:
465 case ACTIVE_HIGH:
466 if (level)
467 group->request |= interrupt;
468 break;
469 case NEGATIVE_EDGE:
470 case POSITIVE_EDGE:
471 group->request |= interrupt;
472 }
473
474 /* force a corresponding output */
475 switch (group->type)
476 {
477
478 case NMI_GROUP:
479 {
480 /* for NMI's the event is the trigger */
481 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
482 my_port, gid, iid));
483 if ((group->request & group->enable) != 0)
484 {
485 HW_TRACE ((me, "port-out NMI"));
486 hw_port_event (me, NMI_PORT, 1);
487 }
488 break;
489 }
490
491 case LEVEL_GROUP:
492 {
493 /* if an interrupt is now pending */
494 HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
495 my_port, gid, iid));
496 push_interrupt_level (me, controller);
497 break;
498 }
499 }
500 break;
501 }
502
503 }
504 }
505
506 /* Read/write to to an ICR (group control register) */
507
508 static struct mn103int_group *
509 decode_group (struct hw *me,
510 struct mn103int *controller,
511 unsigned_word base,
512 unsigned_word *offset)
513 {
514 int gid = (base / 4) % NR_GROUPS;
515 *offset = (base % 4);
516 return &controller->group[gid];
517 }
518
519 static unsigned8
520 read_icr (struct hw *me,
521 struct mn103int *controller,
522 unsigned_word base)
523 {
524 unsigned_word offset;
525 struct mn103int_group *group = decode_group (me, controller, base, &offset);
526 unsigned8 val = 0;
527 switch (group->type)
528 {
529
530 case NMI_GROUP:
531 switch (offset)
532 {
533 case 0:
534 val = INSERT_ID (group->request);
535 HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x",
536 group->gid, val));
537 break;
538 default:
539 break;
540 }
541 break;
542
543 case LEVEL_GROUP:
544 switch (offset)
545 {
546 case 0:
547 val = (INSERT_IR (group->request)
548 | INSERT_ID (group->request & group->enable));
549 HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x",
550 group->gid, val));
551 break;
552 case 1:
553 val = (INSERT_LV (group->level)
554 | INSERT_IE (group->enable));
555 HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x",
556 group->gid, val));
557 break;
558 }
559 break;
560
561 default:
562 break;
563
564 }
565
566 return val;
567 }
568
569 static void
570 write_icr (struct hw *me,
571 struct mn103int *controller,
572 unsigned_word base,
573 unsigned8 val)
574 {
575 unsigned_word offset;
576 struct mn103int_group *group = decode_group (me, controller, base, &offset);
577 switch (group->type)
578 {
579
580 case NMI_GROUP:
581 switch (offset)
582 {
583 case 0:
584 HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x",
585 group->gid, val));
586 group->request &= ~EXTRACT_ID (val);
587 break;
588 default:
589 break;
590 }
591 break;
592
593 case LEVEL_GROUP:
594 switch (offset)
595 {
596 case 0: /* request/detect */
597 /* Clear any ID bits and then set them according to IR */
598 HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x",
599 group->gid, val,
600 group->request, EXTRACT_IR (val), EXTRACT_ID (val)));
601 group->request =
602 ((EXTRACT_IR (val) & EXTRACT_ID (val))
603 | (EXTRACT_IR (val) & group->request)
604 | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request));
605 break;
606 case 1: /* level/enable */
607 HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x",
608 group->gid, val));
609 group->level = EXTRACT_LV (val);
610 group->enable = EXTRACT_IE (val);
611 break;
612 default:
613 /* ignore */
614 break;
615 }
616 push_interrupt_level (me, controller);
617 break;
618
619 default:
620 break;
621
622 }
623 }
624
625
626 /* Read the IAGR (Interrupt accepted group register) */
627
628 static unsigned8
629 read_iagr (struct hw *me,
630 struct mn103int *controller,
631 unsigned_word offset)
632 {
633 unsigned8 val;
634 switch (offset)
635 {
636 case 0:
637 {
638 if (!(controller->group[controller->interrupt_accepted_group].request
639 & controller->group[controller->interrupt_accepted_group].enable))
640 {
641 /* oops, lost the request */
642 val = 0;
643 HW_TRACE ((me, "read-iagr:0 lost-0"));
644 }
645 else
646 {
647 val = (controller->interrupt_accepted_group << 2);
648 HW_TRACE ((me, "read-iagr:0 %d", (int) val));
649 }
650 break;
651 }
652 case 1:
653 val = 0;
654 HW_TRACE ((me, "read-iagr:1 %d", (int) val));
655 break;
656 default:
657 val = 0;
658 HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset));
659 break;
660 }
661 return val;
662 }
663
664
665 /* Reads/writes to the EXTMD (external interrupt trigger configuration
666 register) */
667
668 static struct mn103int_group *
669 external_group (struct mn103int *controller,
670 unsigned_word offset)
671 {
672 switch (offset)
673 {
674 case 0:
675 return &controller->group[IRQ0_PORT/4];
676 case 1:
677 return &controller->group[IRQ4_PORT/4];
678 default:
679 return NULL;
680 }
681 }
682
683 static unsigned8
684 read_extmd (struct hw *me,
685 struct mn103int *controller,
686 unsigned_word offset)
687 {
688 int gid;
689 unsigned8 val = 0;
690 struct mn103int_group *group = external_group (controller, offset);
691 if (group != NULL)
692 {
693 for (gid = 0; gid < 4; gid++)
694 {
695 val |= (group[gid].trigger << (gid * 2));
696 }
697 }
698 HW_TRACE ((me, "read-extmd 0x%02lx", (long) val));
699 return val;
700 }
701
702 static void
703 write_extmd (struct hw *me,
704 struct mn103int *controller,
705 unsigned_word offset,
706 unsigned8 val)
707 {
708 int gid;
709 struct mn103int_group *group = external_group (controller, offset);
710 if (group != NULL)
711 {
712 for (gid = 0; gid < 4; gid++)
713 {
714 group[gid].trigger = (val >> (gid * 2)) & 0x3;
715 /* MAYBE: interrupts already pending? */
716 }
717 }
718 HW_TRACE ((me, "write-extmd 0x%02lx", (long) val));
719 }
720
721
722 /* generic read/write */
723
724 static int
725 decode_addr (struct hw *me,
726 struct mn103int *controller,
727 unsigned_word address,
728 unsigned_word *offset)
729 {
730 int i;
731 for (i = 0; i < NR_BLOCKS; i++)
732 {
733 if (address >= controller->block[i].base
734 && address <= controller->block[i].bound)
735 {
736 *offset = address - controller->block[i].base;
737 return i;
738 }
739 }
740 hw_abort (me, "bad address");
741 return -1;
742 }
743
744 static unsigned
745 mn103int_io_read_buffer (struct hw *me,
746 void *dest,
747 int space,
748 unsigned_word base,
749 unsigned nr_bytes)
750 {
751 struct mn103int *controller = hw_data (me);
752 unsigned8 *buf = dest;
753 unsigned byte;
754 /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */
755 for (byte = 0; byte < nr_bytes; byte++)
756 {
757 unsigned_word address = base + byte;
758 unsigned_word offset;
759 switch (decode_addr (me, controller, address, &offset))
760 {
761 case ICR_BLOCK:
762 buf[byte] = read_icr (me, controller, offset);
763 break;
764 case IAGR_BLOCK:
765 buf[byte] = read_iagr (me, controller, offset);
766 break;
767 case EXTMD_BLOCK:
768 buf[byte] = read_extmd (me, controller, offset);
769 break;
770 default:
771 hw_abort (me, "bad switch");
772 }
773 }
774 return nr_bytes;
775 }
776
777 static unsigned
778 mn103int_io_write_buffer (struct hw *me,
779 const void *source,
780 int space,
781 unsigned_word base,
782 unsigned nr_bytes)
783 {
784 struct mn103int *controller = hw_data (me);
785 const unsigned8 *buf = source;
786 unsigned byte;
787 /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */
788 for (byte = 0; byte < nr_bytes; byte++)
789 {
790 unsigned_word address = base + byte;
791 unsigned_word offset;
792 switch (decode_addr (me, controller, address, &offset))
793 {
794 case ICR_BLOCK:
795 write_icr (me, controller, offset, buf[byte]);
796 break;
797 case IAGR_BLOCK:
798 /* not allowed */
799 break;
800 case EXTMD_BLOCK:
801 write_extmd (me, controller, offset, buf[byte]);
802 break;
803 default:
804 hw_abort (me, "bad switch");
805 }
806 }
807 return nr_bytes;
808 }
809
810 static int
811 mn103int_ioctl(struct hw *me,
812 hw_ioctl_request request,
813 va_list ap)
814 {
815 struct mn103int *controller = (struct mn103int *)hw_data(me);
816 controller->group[0].request = EXTRACT_ID(4);
817 mn103int_port_event(me, 2 /* nmi_port(syserr) */, NULL, 0, 0);
818 }
819
820
821 const struct hw_descriptor dv_mn103int_descriptor[] = {
822 { "mn103int", mn103int_finish, },
823 { NULL },
824 };