Merge https://gitlab.denx.de/u-boot/custodians/u-boot-spi
[platform/kernel/u-boot.git] / arch / x86 / cpu / i386 / interrupt.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008-2011
4  * Graeme Russ, <graeme.russ@gmail.com>
5  *
6  * (C) Copyright 2002
7  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
8  *
9  * Portions of this file are derived from the Linux kernel source
10  *  Copyright (C) 1991, 1992  Linus Torvalds
11  */
12
13 #include <common.h>
14 #include <dm.h>
15 #include <efi_loader.h>
16 #include <hang.h>
17 #include <init.h>
18 #include <irq.h>
19 #include <irq_func.h>
20 #include <asm/control_regs.h>
21 #include <asm/i8259.h>
22 #include <asm/interrupt.h>
23 #include <asm/io.h>
24 #include <asm/lapic.h>
25 #include <asm/processor-flags.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 #define DECLARE_INTERRUPT(x) \
30         ".globl irq_"#x"\n" \
31         ".hidden irq_"#x"\n" \
32         ".type irq_"#x", @function\n" \
33         "irq_"#x":\n" \
34         "pushl $"#x"\n" \
35         "jmp.d32 irq_common_entry\n"
36
37 static char *exceptions[] = {
38         "Divide Error",
39         "Debug",
40         "NMI Interrupt",
41         "Breakpoint",
42         "Overflow",
43         "BOUND Range Exceeded",
44         "Invalid Opcode (Undefined Opcode)",
45         "Device Not Available (No Math Coprocessor)",
46         "Double Fault",
47         "Coprocessor Segment Overrun",
48         "Invalid TSS",
49         "Segment Not Present",
50         "Stack Segment Fault",
51         "General Protection",
52         "Page Fault",
53         "Reserved",
54         "x87 FPU Floating-Point Error",
55         "Alignment Check",
56         "Machine Check",
57         "SIMD Floating-Point Exception",
58         "Virtualization Exception",
59         "Reserved",
60         "Reserved",
61         "Reserved",
62         "Reserved",
63         "Reserved",
64         "Reserved",
65         "Reserved",
66         "Reserved",
67         "Reserved",
68         "Reserved",
69         "Reserved"
70 };
71
72 /**
73  * show_efi_loaded_images() - show loaded UEFI images
74  *
75  * List all loaded UEFI images.
76  *
77  * @eip:        instruction pointer
78  */
79 static void show_efi_loaded_images(uintptr_t eip)
80 {
81         efi_print_image_infos((void *)eip);
82 }
83
84 static void dump_regs(struct irq_regs *regs)
85 {
86         unsigned long cs, eip, eflags;
87         unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
88         unsigned long d0, d1, d2, d3, d6, d7;
89         unsigned long sp;
90
91         /*
92          * Some exceptions cause an error code to be saved on the current stack
93          * after the EIP value. We should extract CS/EIP/EFLAGS from different
94          * position on the stack based on the exception number.
95          */
96         switch (regs->irq_id) {
97         case EXC_DF:
98         case EXC_TS:
99         case EXC_NP:
100         case EXC_SS:
101         case EXC_GP:
102         case EXC_PF:
103         case EXC_AC:
104                 cs = regs->context.ctx2.xcs;
105                 eip = regs->context.ctx2.eip;
106                 eflags = regs->context.ctx2.eflags;
107                 /* We should fix up the ESP due to error code */
108                 regs->esp += 4;
109                 break;
110         default:
111                 cs = regs->context.ctx1.xcs;
112                 eip = regs->context.ctx1.eip;
113                 eflags = regs->context.ctx1.eflags;
114                 break;
115         }
116
117         printf("EIP: %04x:[<%08lx>] EFLAGS: %08lx\n",
118                         (u16)cs, eip, eflags);
119         if (gd->flags & GD_FLG_RELOC)
120                 printf("Original EIP :[<%08lx>]\n", eip - gd->reloc_off);
121
122         printf("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
123                 regs->eax, regs->ebx, regs->ecx, regs->edx);
124         printf("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
125                 regs->esi, regs->edi, regs->ebp, regs->esp);
126         printf(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
127                (u16)regs->xds, (u16)regs->xes, (u16)regs->xfs,
128                (u16)regs->xgs, (u16)regs->xss);
129
130         cr0 = read_cr0();
131         cr2 = read_cr2();
132         cr3 = read_cr3();
133         cr4 = read_cr4();
134
135         printf("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
136                         cr0, cr2, cr3, cr4);
137
138         d0 = get_debugreg(0);
139         d1 = get_debugreg(1);
140         d2 = get_debugreg(2);
141         d3 = get_debugreg(3);
142
143         printf("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
144                         d0, d1, d2, d3);
145
146         d6 = get_debugreg(6);
147         d7 = get_debugreg(7);
148         printf("DR6: %08lx DR7: %08lx\n",
149                         d6, d7);
150
151         printf("Stack:\n");
152         sp = regs->esp;
153
154         sp += 64;
155
156         while (sp > (regs->esp - 16)) {
157                 if (sp == regs->esp)
158                         printf("--->");
159                 else
160                         printf("    ");
161                 printf("0x%8.8lx : 0x%8.8lx\n", sp, (ulong)readl(sp));
162                 sp -= 4;
163         }
164         show_efi_loaded_images(eip);
165 }
166
167 static void do_exception(struct irq_regs *regs)
168 {
169         printf("%s\n", exceptions[regs->irq_id]);
170         dump_regs(regs);
171         hang();
172 }
173
174 struct idt_entry {
175         u16     base_low;
176         u16     selector;
177         u8      res;
178         u8      access;
179         u16     base_high;
180 } __packed;
181
182 struct desc_ptr {
183         unsigned short size;
184         unsigned long address;
185 } __packed;
186
187 struct idt_entry idt[256] __aligned(16);
188
189 struct desc_ptr idt_ptr;
190
191 static inline void load_idt(const struct desc_ptr *dtr)
192 {
193         asm volatile("cs lidt %0" : : "m" (*dtr));
194 }
195
196 void set_vector(u8 intnum, void *routine)
197 {
198         idt[intnum].base_high = (u16)((ulong)(routine) >> 16);
199         idt[intnum].base_low = (u16)((ulong)(routine) & 0xffff);
200 }
201
202 /*
203  * Ideally these would be defined static to avoid a checkpatch warning, but
204  * the compiler cannot see them in the inline asm and complains that they
205  * aren't defined
206  */
207 void irq_0(void);
208 void irq_1(void);
209
210 int cpu_init_interrupts(void)
211 {
212         int i;
213
214         int irq_entry_size = irq_1 - irq_0;
215         void *irq_entry = (void *)irq_0;
216
217         /* Setup the IDT */
218         for (i = 0; i < 256; i++) {
219                 idt[i].access = 0x8e;
220                 idt[i].res = 0;
221                 idt[i].selector = X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE;
222                 set_vector(i, irq_entry);
223                 irq_entry += irq_entry_size;
224         }
225
226         idt_ptr.size = 256 * 8 - 1;
227         idt_ptr.address = (unsigned long) idt;
228
229         load_idt(&idt_ptr);
230
231         return 0;
232 }
233
234 void *x86_get_idt(void)
235 {
236         return &idt_ptr;
237 }
238
239 void __do_irq(int irq)
240 {
241         printf("Unhandled IRQ : %d\n", irq);
242 }
243 void do_irq(int irq) __attribute__((weak, alias("__do_irq")));
244
245 void enable_interrupts(void)
246 {
247         asm("sti\n");
248 }
249
250 int disable_interrupts(void)
251 {
252         long flags;
253
254 #if CONFIG_IS_ENABLED(X86_64)
255         asm volatile ("pushfq ; popq %0 ; cli\n" : "=g" (flags) : );
256 #else
257         asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : );
258 #endif
259         return flags & X86_EFLAGS_IF;
260 }
261
262 int interrupt_init(void)
263 {
264         struct udevice *dev;
265         int ret;
266
267         if (!ll_boot_init())
268                 return 0;
269
270         /* Try to set up the interrupt router, but don't require one */
271         ret = irq_first_device_type(X86_IRQT_BASE, &dev);
272         if (ret && ret != -ENODEV)
273                 return ret;
274
275         /*
276          * When running as an EFI application we are not in control of
277          * interrupts and should leave them alone.
278          */
279 #ifndef CONFIG_EFI_APP
280         /* Just in case... */
281         disable_interrupts();
282
283 #ifdef CONFIG_I8259_PIC
284         /* Initialize the master/slave i8259 pic */
285         i8259_init();
286 #endif
287
288 #ifdef CONFIG_APIC
289         lapic_setup();
290 #endif
291
292         /* Initialize core interrupt and exception functionality of CPU */
293         cpu_init_interrupts();
294
295         /*
296          * It is now safe to enable interrupts.
297          *
298          * TODO(sjg@chromium.org): But we don't handle these correctly when
299          * booted from EFI.
300          */
301         enable_interrupts();
302 #endif
303
304         return 0;
305 }
306
307 /* IRQ Low-Level Service Routine */
308 void irq_llsr(struct irq_regs *regs)
309 {
310         /*
311          * For detailed description of each exception, refer to:
312          * Intel® 64 and IA-32 Architectures Software Developer's Manual
313          * Volume 1: Basic Architecture
314          * Order Number: 253665-029US, November 2008
315          * Table 6-1. Exceptions and Interrupts
316          */
317         if (regs->irq_id < 32) {
318                 /* Architecture defined exception */
319                 do_exception(regs);
320         } else {
321                 /* Hardware or User IRQ */
322                 do_irq(regs->irq_id);
323         }
324 }
325
326 /*
327  * OK - This looks really horrible, but it serves a purpose - It helps create
328  * fully relocatable code.
329  *  - The call to irq_llsr will be a relative jump
330  *  - The IRQ entries will be guaranteed to be in order
331  *  Interrupt entries are now very small (a push and a jump) but they are
332  *  now slower (all registers pushed on stack which provides complete
333  *  crash dumps in the low level handlers
334  *
335  * Interrupt Entry Point:
336  *  - Interrupt has caused eflags, CS and EIP to be pushed
337  *  - Interrupt Vector Handler has pushed orig_eax
338  *  - pt_regs.esp needs to be adjusted by 40 bytes:
339  *      12 bytes pushed by CPU (EFLAGSF, CS, EIP)
340  *      4 bytes pushed by vector handler (irq_id)
341  *      24 bytes pushed before SP (SS, GS, FS, ES, DS, EAX)
342  *      NOTE: Only longs are pushed on/popped off the stack!
343  */
344 asm(".globl irq_common_entry\n" \
345         ".hidden irq_common_entry\n" \
346         ".type irq_common_entry, @function\n" \
347         "irq_common_entry:\n" \
348         "cld\n" \
349         "pushl %ss\n" \
350         "pushl %gs\n" \
351         "pushl %fs\n" \
352         "pushl %es\n" \
353         "pushl %ds\n" \
354         "pushl %eax\n" \
355         "movl  %esp, %eax\n" \
356         "addl  $40, %eax\n" \
357         "pushl %eax\n" \
358         "pushl %ebp\n" \
359         "pushl %edi\n" \
360         "pushl %esi\n" \
361         "pushl %edx\n" \
362         "pushl %ecx\n" \
363         "pushl %ebx\n" \
364         "mov   %esp, %eax\n" \
365         "call irq_llsr\n" \
366         "popl %ebx\n" \
367         "popl %ecx\n" \
368         "popl %edx\n" \
369         "popl %esi\n" \
370         "popl %edi\n" \
371         "popl %ebp\n" \
372         "popl %eax\n" \
373         "popl %eax\n" \
374         "popl %ds\n" \
375         "popl %es\n" \
376         "popl %fs\n" \
377         "popl %gs\n" \
378         "popl %ss\n" \
379         "add  $4, %esp\n" \
380         "iret\n" \
381         DECLARE_INTERRUPT(0) \
382         DECLARE_INTERRUPT(1) \
383         DECLARE_INTERRUPT(2) \
384         DECLARE_INTERRUPT(3) \
385         DECLARE_INTERRUPT(4) \
386         DECLARE_INTERRUPT(5) \
387         DECLARE_INTERRUPT(6) \
388         DECLARE_INTERRUPT(7) \
389         DECLARE_INTERRUPT(8) \
390         DECLARE_INTERRUPT(9) \
391         DECLARE_INTERRUPT(10) \
392         DECLARE_INTERRUPT(11) \
393         DECLARE_INTERRUPT(12) \
394         DECLARE_INTERRUPT(13) \
395         DECLARE_INTERRUPT(14) \
396         DECLARE_INTERRUPT(15) \
397         DECLARE_INTERRUPT(16) \
398         DECLARE_INTERRUPT(17) \
399         DECLARE_INTERRUPT(18) \
400         DECLARE_INTERRUPT(19) \
401         DECLARE_INTERRUPT(20) \
402         DECLARE_INTERRUPT(21) \
403         DECLARE_INTERRUPT(22) \
404         DECLARE_INTERRUPT(23) \
405         DECLARE_INTERRUPT(24) \
406         DECLARE_INTERRUPT(25) \
407         DECLARE_INTERRUPT(26) \
408         DECLARE_INTERRUPT(27) \
409         DECLARE_INTERRUPT(28) \
410         DECLARE_INTERRUPT(29) \
411         DECLARE_INTERRUPT(30) \
412         DECLARE_INTERRUPT(31) \
413         DECLARE_INTERRUPT(32) \
414         DECLARE_INTERRUPT(33) \
415         DECLARE_INTERRUPT(34) \
416         DECLARE_INTERRUPT(35) \
417         DECLARE_INTERRUPT(36) \
418         DECLARE_INTERRUPT(37) \
419         DECLARE_INTERRUPT(38) \
420         DECLARE_INTERRUPT(39) \
421         DECLARE_INTERRUPT(40) \
422         DECLARE_INTERRUPT(41) \
423         DECLARE_INTERRUPT(42) \
424         DECLARE_INTERRUPT(43) \
425         DECLARE_INTERRUPT(44) \
426         DECLARE_INTERRUPT(45) \
427         DECLARE_INTERRUPT(46) \
428         DECLARE_INTERRUPT(47) \
429         DECLARE_INTERRUPT(48) \
430         DECLARE_INTERRUPT(49) \
431         DECLARE_INTERRUPT(50) \
432         DECLARE_INTERRUPT(51) \
433         DECLARE_INTERRUPT(52) \
434         DECLARE_INTERRUPT(53) \
435         DECLARE_INTERRUPT(54) \
436         DECLARE_INTERRUPT(55) \
437         DECLARE_INTERRUPT(56) \
438         DECLARE_INTERRUPT(57) \
439         DECLARE_INTERRUPT(58) \
440         DECLARE_INTERRUPT(59) \
441         DECLARE_INTERRUPT(60) \
442         DECLARE_INTERRUPT(61) \
443         DECLARE_INTERRUPT(62) \
444         DECLARE_INTERRUPT(63) \
445         DECLARE_INTERRUPT(64) \
446         DECLARE_INTERRUPT(65) \
447         DECLARE_INTERRUPT(66) \
448         DECLARE_INTERRUPT(67) \
449         DECLARE_INTERRUPT(68) \
450         DECLARE_INTERRUPT(69) \
451         DECLARE_INTERRUPT(70) \
452         DECLARE_INTERRUPT(71) \
453         DECLARE_INTERRUPT(72) \
454         DECLARE_INTERRUPT(73) \
455         DECLARE_INTERRUPT(74) \
456         DECLARE_INTERRUPT(75) \
457         DECLARE_INTERRUPT(76) \
458         DECLARE_INTERRUPT(77) \
459         DECLARE_INTERRUPT(78) \
460         DECLARE_INTERRUPT(79) \
461         DECLARE_INTERRUPT(80) \
462         DECLARE_INTERRUPT(81) \
463         DECLARE_INTERRUPT(82) \
464         DECLARE_INTERRUPT(83) \
465         DECLARE_INTERRUPT(84) \
466         DECLARE_INTERRUPT(85) \
467         DECLARE_INTERRUPT(86) \
468         DECLARE_INTERRUPT(87) \
469         DECLARE_INTERRUPT(88) \
470         DECLARE_INTERRUPT(89) \
471         DECLARE_INTERRUPT(90) \
472         DECLARE_INTERRUPT(91) \
473         DECLARE_INTERRUPT(92) \
474         DECLARE_INTERRUPT(93) \
475         DECLARE_INTERRUPT(94) \
476         DECLARE_INTERRUPT(95) \
477         DECLARE_INTERRUPT(97) \
478         DECLARE_INTERRUPT(96) \
479         DECLARE_INTERRUPT(98) \
480         DECLARE_INTERRUPT(99) \
481         DECLARE_INTERRUPT(100) \
482         DECLARE_INTERRUPT(101) \
483         DECLARE_INTERRUPT(102) \
484         DECLARE_INTERRUPT(103) \
485         DECLARE_INTERRUPT(104) \
486         DECLARE_INTERRUPT(105) \
487         DECLARE_INTERRUPT(106) \
488         DECLARE_INTERRUPT(107) \
489         DECLARE_INTERRUPT(108) \
490         DECLARE_INTERRUPT(109) \
491         DECLARE_INTERRUPT(110) \
492         DECLARE_INTERRUPT(111) \
493         DECLARE_INTERRUPT(112) \
494         DECLARE_INTERRUPT(113) \
495         DECLARE_INTERRUPT(114) \
496         DECLARE_INTERRUPT(115) \
497         DECLARE_INTERRUPT(116) \
498         DECLARE_INTERRUPT(117) \
499         DECLARE_INTERRUPT(118) \
500         DECLARE_INTERRUPT(119) \
501         DECLARE_INTERRUPT(120) \
502         DECLARE_INTERRUPT(121) \
503         DECLARE_INTERRUPT(122) \
504         DECLARE_INTERRUPT(123) \
505         DECLARE_INTERRUPT(124) \
506         DECLARE_INTERRUPT(125) \
507         DECLARE_INTERRUPT(126) \
508         DECLARE_INTERRUPT(127) \
509         DECLARE_INTERRUPT(128) \
510         DECLARE_INTERRUPT(129) \
511         DECLARE_INTERRUPT(130) \
512         DECLARE_INTERRUPT(131) \
513         DECLARE_INTERRUPT(132) \
514         DECLARE_INTERRUPT(133) \
515         DECLARE_INTERRUPT(134) \
516         DECLARE_INTERRUPT(135) \
517         DECLARE_INTERRUPT(136) \
518         DECLARE_INTERRUPT(137) \
519         DECLARE_INTERRUPT(138) \
520         DECLARE_INTERRUPT(139) \
521         DECLARE_INTERRUPT(140) \
522         DECLARE_INTERRUPT(141) \
523         DECLARE_INTERRUPT(142) \
524         DECLARE_INTERRUPT(143) \
525         DECLARE_INTERRUPT(144) \
526         DECLARE_INTERRUPT(145) \
527         DECLARE_INTERRUPT(146) \
528         DECLARE_INTERRUPT(147) \
529         DECLARE_INTERRUPT(148) \
530         DECLARE_INTERRUPT(149) \
531         DECLARE_INTERRUPT(150) \
532         DECLARE_INTERRUPT(151) \
533         DECLARE_INTERRUPT(152) \
534         DECLARE_INTERRUPT(153) \
535         DECLARE_INTERRUPT(154) \
536         DECLARE_INTERRUPT(155) \
537         DECLARE_INTERRUPT(156) \
538         DECLARE_INTERRUPT(157) \
539         DECLARE_INTERRUPT(158) \
540         DECLARE_INTERRUPT(159) \
541         DECLARE_INTERRUPT(160) \
542         DECLARE_INTERRUPT(161) \
543         DECLARE_INTERRUPT(162) \
544         DECLARE_INTERRUPT(163) \
545         DECLARE_INTERRUPT(164) \
546         DECLARE_INTERRUPT(165) \
547         DECLARE_INTERRUPT(166) \
548         DECLARE_INTERRUPT(167) \
549         DECLARE_INTERRUPT(168) \
550         DECLARE_INTERRUPT(169) \
551         DECLARE_INTERRUPT(170) \
552         DECLARE_INTERRUPT(171) \
553         DECLARE_INTERRUPT(172) \
554         DECLARE_INTERRUPT(173) \
555         DECLARE_INTERRUPT(174) \
556         DECLARE_INTERRUPT(175) \
557         DECLARE_INTERRUPT(176) \
558         DECLARE_INTERRUPT(177) \
559         DECLARE_INTERRUPT(178) \
560         DECLARE_INTERRUPT(179) \
561         DECLARE_INTERRUPT(180) \
562         DECLARE_INTERRUPT(181) \
563         DECLARE_INTERRUPT(182) \
564         DECLARE_INTERRUPT(183) \
565         DECLARE_INTERRUPT(184) \
566         DECLARE_INTERRUPT(185) \
567         DECLARE_INTERRUPT(186) \
568         DECLARE_INTERRUPT(187) \
569         DECLARE_INTERRUPT(188) \
570         DECLARE_INTERRUPT(189) \
571         DECLARE_INTERRUPT(190) \
572         DECLARE_INTERRUPT(191) \
573         DECLARE_INTERRUPT(192) \
574         DECLARE_INTERRUPT(193) \
575         DECLARE_INTERRUPT(194) \
576         DECLARE_INTERRUPT(195) \
577         DECLARE_INTERRUPT(196) \
578         DECLARE_INTERRUPT(197) \
579         DECLARE_INTERRUPT(198) \
580         DECLARE_INTERRUPT(199) \
581         DECLARE_INTERRUPT(200) \
582         DECLARE_INTERRUPT(201) \
583         DECLARE_INTERRUPT(202) \
584         DECLARE_INTERRUPT(203) \
585         DECLARE_INTERRUPT(204) \
586         DECLARE_INTERRUPT(205) \
587         DECLARE_INTERRUPT(206) \
588         DECLARE_INTERRUPT(207) \
589         DECLARE_INTERRUPT(208) \
590         DECLARE_INTERRUPT(209) \
591         DECLARE_INTERRUPT(210) \
592         DECLARE_INTERRUPT(211) \
593         DECLARE_INTERRUPT(212) \
594         DECLARE_INTERRUPT(213) \
595         DECLARE_INTERRUPT(214) \
596         DECLARE_INTERRUPT(215) \
597         DECLARE_INTERRUPT(216) \
598         DECLARE_INTERRUPT(217) \
599         DECLARE_INTERRUPT(218) \
600         DECLARE_INTERRUPT(219) \
601         DECLARE_INTERRUPT(220) \
602         DECLARE_INTERRUPT(221) \
603         DECLARE_INTERRUPT(222) \
604         DECLARE_INTERRUPT(223) \
605         DECLARE_INTERRUPT(224) \
606         DECLARE_INTERRUPT(225) \
607         DECLARE_INTERRUPT(226) \
608         DECLARE_INTERRUPT(227) \
609         DECLARE_INTERRUPT(228) \
610         DECLARE_INTERRUPT(229) \
611         DECLARE_INTERRUPT(230) \
612         DECLARE_INTERRUPT(231) \
613         DECLARE_INTERRUPT(232) \
614         DECLARE_INTERRUPT(233) \
615         DECLARE_INTERRUPT(234) \
616         DECLARE_INTERRUPT(235) \
617         DECLARE_INTERRUPT(236) \
618         DECLARE_INTERRUPT(237) \
619         DECLARE_INTERRUPT(238) \
620         DECLARE_INTERRUPT(239) \
621         DECLARE_INTERRUPT(240) \
622         DECLARE_INTERRUPT(241) \
623         DECLARE_INTERRUPT(242) \
624         DECLARE_INTERRUPT(243) \
625         DECLARE_INTERRUPT(244) \
626         DECLARE_INTERRUPT(245) \
627         DECLARE_INTERRUPT(246) \
628         DECLARE_INTERRUPT(247) \
629         DECLARE_INTERRUPT(248) \
630         DECLARE_INTERRUPT(249) \
631         DECLARE_INTERRUPT(250) \
632         DECLARE_INTERRUPT(251) \
633         DECLARE_INTERRUPT(252) \
634         DECLARE_INTERRUPT(253) \
635         DECLARE_INTERRUPT(254) \
636         DECLARE_INTERRUPT(255));