summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu/i386/cpu_asm.s
blob: 2bc63fa1d58df41851b7b06a87ae34cf70d6ef40 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
/*  cpu_asm.s
 *
 *  This file contains all assembly code for the Intel i386 implementation
 *  of RTEMS.
 *
 *  COPYRIGHT (c) 1989-1998.
 *  On-Line Applications Research Corporation (OAR).
 *  Copyright assigned to U.S. Government, 1994.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 */

#include <asm.h>

/*
 * Format of i386 Register structure
 */

.set REG_EFLAGS,  0
.set REG_ESP,     REG_EFLAGS + 4
.set REG_EBP,     REG_ESP + 4
.set REG_EBX,     REG_EBP + 4
.set REG_ESI,     REG_EBX + 4
.set REG_EDI,     REG_ESI + 4
.set SIZE_REGS,   REG_EDI + 4

        BEGIN_CODE

/*
 *  void _CPU_Context_switch( run_context, heir_context )
 *
 *  This routine performs a normal non-FP context.
 */

        .p2align  1
        PUBLIC (_CPU_Context_switch)

.set RUNCONTEXT_ARG,   4                   # save context argument
.set HEIRCONTEXT_ARG,  8                   # restore context argument

SYM (_CPU_Context_switch):
        movl      RUNCONTEXT_ARG(esp),eax  # eax = running threads context
        pushf                              # push eflags
        popl      REG_EFLAGS(eax)          # save eflags
        movl      esp,REG_ESP(eax)         # save stack pointer
        movl      ebp,REG_EBP(eax)         # save base pointer
        movl      ebx,REG_EBX(eax)         # save ebx
        movl      esi,REG_ESI(eax)         # save source register
        movl      edi,REG_EDI(eax)         # save destination register

        movl      HEIRCONTEXT_ARG(esp),eax # eax = heir threads context

restore:
        pushl     REG_EFLAGS(eax)          # push eflags
        popf                               # restore eflags
        movl      REG_ESP(eax),esp         # restore stack pointer
        movl      REG_EBP(eax),ebp         # restore base pointer
        movl      REG_EBX(eax),ebx         # restore ebx
        movl      REG_ESI(eax),esi         # restore source register
        movl      REG_EDI(eax),edi         # restore destination register
        ret

/*
 *  NOTE: May be unnecessary to reload some registers.
 */

/*
 *  void _CPU_Context_restore( new_context )
 *
 *  This routine performs a normal non-FP context.
 */

        PUBLIC (_CPU_Context_restore)

.set NEWCONTEXT_ARG,   4                   # context to restore argument

SYM (_CPU_Context_restore):

        movl      NEWCONTEXT_ARG(esp),eax  # eax = running threads context
        jmp       restore

/*PAGE
 *  void _CPU_Context_save_fp_context( &fp_context_ptr )
 *  void _CPU_Context_restore_fp_context( &fp_context_ptr )
 *
 *  This section is used to context switch an i80287, i80387,
 *  the built-in coprocessor or the i80486 or compatible.
 */

.set FPCONTEXT_ARG,   4                    # FP context argument

        .p2align  1
        PUBLIC (_CPU_Context_save_fp)
SYM (_CPU_Context_save_fp):
        movl      FPCONTEXT_ARG(esp),eax   # eax = &ptr to FP context area
        movl      (eax),eax                # eax = FP context area
        fsave     (eax)                    # save FP context
        ret

        .p2align  1
        PUBLIC (_CPU_Context_restore_fp)
SYM (_CPU_Context_restore_fp):
        movl      FPCONTEXT_ARG(esp),eax   # eax = &ptr to FP context area
        movl      (eax),eax                # eax = FP context area
        frstor    (eax)                    # restore FP context
        ret

/*PAGE
 *  void _ISR_Handler()
 *
 *  This routine provides the RTEMS interrupt management.
 *
 *  NOTE:
 *    Upon entry, the stack will contain a stack frame back to the
 *    interrupted task.  If dispatching is enabled, this is the
 *    outer most interrupt, and (a context switch is necessary or
 *    the current task has signals), then set up the stack to
 *    transfer control to the interrupt dispatcher.
 */

.set SET_SEGMENT_REGISTERS_IN_INTERRUPT, 0

.set SAVED_REGS     , 32                   # space consumed by saved regs
.set EIP_OFFSET     , SAVED_REGS           # offset of tasks eip
.set CS_OFFSET      , EIP_OFFSET+4         # offset of tasks code segment
.set EFLAGS_OFFSET  , CS_OFFSET+4          # offset of tasks eflags

        .p2align  1
        PUBLIC (_ISR_Handler)

SYM (_ISR_Handler):
       /*
        *  Before this was point is reached the vectors unique
        *  entry point did the following:
        *
        *     1. saved all registers with a "pusha"
        *     2. put the vector number in eax.
        *
        * BEGINNING OF ESTABLISH SEGMENTS
        *
        *  WARNING: If an interrupt can occur when the segments are
        *           not correct, then this is where we should establish
        *           the segments.  In addition to establishing the
        *           segments, it may be necessary to establish a stack
        *           in the current data area on the outermost interrupt.
        *
        *  NOTE:  If the previous values of the segment registers are
        *         pushed, do not forget to adjust SAVED_REGS.
        *
        *  NOTE:  Make sure the exit code which restores these
        *         when this type of code is needed.
        */

       /***** ESTABLISH SEGMENTS CODE GOES HERE  ******/

       /*
        * END OF ESTABLISH SEGMENTS
        */

        /*
         *  Now switch stacks if necessary
         */

        movl      esp, edx                  # edx = previous stack pointer
        cmpl      $0, SYM (_ISR_Nest_level) # is this the outermost interrupt?
        jne       nested                    # No, then continue
        movl      SYM (_CPU_Interrupt_stack_high), esp

        /*
         *  We want to insure that the old stack pointer is on the
         *  stack we will be on at the end of the ISR when we restore it.
         *  By saving it on every interrupt, all we have to do is pop it
         *  near the end of every interrupt.
         */

nested:
        pushl     edx                       # save the previous stack pointer
        incl      SYM (_ISR_Nest_level)     # one nest level deeper
        incl      SYM (_Thread_Dispatch_disable_level) # disable multitasking

        # EAX is preloaded with the vector number.
        push      eax                       # push vector number
        mov       SYM (_ISR_Vector_table) (,eax,4),eax
                                            # eax = Users handler
        call      eax                       # invoke user ISR
        pop       eax                       # eax = vector number

        decl      SYM (_ISR_Nest_level)     # one less ISR nest level
                                            # If interrupts are nested,
                                            #   then dispatching is disabled

        decl      SYM (_Thread_Dispatch_disable_level)
                                            # unnest multitasking
                                            # Is dispatch disabled
        jne       exit                      # Yes, then exit

        cmpl      $0, SYM (_Context_Switch_necessary)
                                            # Is task switch necessary?
        jne       bframe                    # Yes, then build stack

        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)
                                            # signals sent to Run_thread
                                            #   while in interrupt handler?
        je        exit                      # No, exit

bframe:
        cli                                 # DISABLE INTERRUPTS!!
        popl      esp                       # restore the stack pointer
        movl      $0, SYM (_ISR_Signals_to_thread_executing)
                                            # push the isf for Isr_dispatch
        push      EFLAGS_OFFSET(esp)        # push tasks eflags
        push      cs                        # cs of Isr_dispatch
        push      $ SYM (_ISR_Dispatch)     # entry point
        iret

exit:
        cli                                 # DISABLE INTERRUPTS!!
        popl      esp                       # restore the stack pointer

       /*
        * BEGINNING OF DE-ESTABLISH SEGMENTS
        *
        *  NOTE:  Make sure there is code here if code is added to
        *         load the segment registers.
        *
        */

       /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/

       /*
        * END OF DE-ESTABLISH SEGMENTS
        */

        popa                                # restore general registers
        iret

/*PAGE
 *  Distinct Interrupt Entry Points
 *
 *  The following macro and the 256 instantiations of the macro
 *  are necessary to determine which interrupt vector occurred.
 *  The following macro allows a unique entry point to be defined
 *  for each vector.
 *
 *  NOTE: There are not spaces around the vector number argument
 *        to the DISTINCT_INTERRUPT_ENTRY macro because m4 will
 *        undesirably generate the symbol "_Isr_handler_ N"
 *        instead of "_Isr_handler_N" like we want.
 */

#define DISTINCT_INTERRUPT_ENTRY(_vector) \
        .p2align 4                         ; \
        PUBLIC (_ISR_Handler_ ## _vector ) ; \
SYM (_ISR_Handler_ ## _vector ):             \
        pusha                              ; \
        xor   eax, eax                     ; \
        movb  $ ## _vector, al             ; \
        jmp   SYM (_ISR_Handler) ;

DISTINCT_INTERRUPT_ENTRY(0)
DISTINCT_INTERRUPT_ENTRY(1)
DISTINCT_INTERRUPT_ENTRY(2)
DISTINCT_INTERRUPT_ENTRY(3)
DISTINCT_INTERRUPT_ENTRY(4)
DISTINCT_INTERRUPT_ENTRY(5)
DISTINCT_INTERRUPT_ENTRY(6)
DISTINCT_INTERRUPT_ENTRY(7)
DISTINCT_INTERRUPT_ENTRY(8)
DISTINCT_INTERRUPT_ENTRY(9)
DISTINCT_INTERRUPT_ENTRY(10)
DISTINCT_INTERRUPT_ENTRY(11)
DISTINCT_INTERRUPT_ENTRY(12)
DISTINCT_INTERRUPT_ENTRY(13)
DISTINCT_INTERRUPT_ENTRY(14)
DISTINCT_INTERRUPT_ENTRY(15)
DISTINCT_INTERRUPT_ENTRY(16)
DISTINCT_INTERRUPT_ENTRY(17)
DISTINCT_INTERRUPT_ENTRY(18)
DISTINCT_INTERRUPT_ENTRY(19)
DISTINCT_INTERRUPT_ENTRY(20)
DISTINCT_INTERRUPT_ENTRY(21)
DISTINCT_INTERRUPT_ENTRY(22)
DISTINCT_INTERRUPT_ENTRY(23)
DISTINCT_INTERRUPT_ENTRY(24)
DISTINCT_INTERRUPT_ENTRY(25)
DISTINCT_INTERRUPT_ENTRY(26)
DISTINCT_INTERRUPT_ENTRY(27)
DISTINCT_INTERRUPT_ENTRY(28)
DISTINCT_INTERRUPT_ENTRY(29)
DISTINCT_INTERRUPT_ENTRY(30)
DISTINCT_INTERRUPT_ENTRY(31)
DISTINCT_INTERRUPT_ENTRY(32)
DISTINCT_INTERRUPT_ENTRY(33)
DISTINCT_INTERRUPT_ENTRY(34)
DISTINCT_INTERRUPT_ENTRY(35)
DISTINCT_INTERRUPT_ENTRY(36)
DISTINCT_INTERRUPT_ENTRY(37)
DISTINCT_INTERRUPT_ENTRY(38)
DISTINCT_INTERRUPT_ENTRY(39)
DISTINCT_INTERRUPT_ENTRY(40)
DISTINCT_INTERRUPT_ENTRY(41)
DISTINCT_INTERRUPT_ENTRY(42)
DISTINCT_INTERRUPT_ENTRY(43)
DISTINCT_INTERRUPT_ENTRY(44)
DISTINCT_INTERRUPT_ENTRY(45)
DISTINCT_INTERRUPT_ENTRY(46)
DISTINCT_INTERRUPT_ENTRY(47)
DISTINCT_INTERRUPT_ENTRY(48)
DISTINCT_INTERRUPT_ENTRY(49)
DISTINCT_INTERRUPT_ENTRY(50)
DISTINCT_INTERRUPT_ENTRY(51)
DISTINCT_INTERRUPT_ENTRY(52)
DISTINCT_INTERRUPT_ENTRY(53)
DISTINCT_INTERRUPT_ENTRY(54)
DISTINCT_INTERRUPT_ENTRY(55)
DISTINCT_INTERRUPT_ENTRY(56)
DISTINCT_INTERRUPT_ENTRY(57)
DISTINCT_INTERRUPT_ENTRY(58)
DISTINCT_INTERRUPT_ENTRY(59)
DISTINCT_INTERRUPT_ENTRY(60)
DISTINCT_INTERRUPT_ENTRY(61)
DISTINCT_INTERRUPT_ENTRY(62)
DISTINCT_INTERRUPT_ENTRY(63)
DISTINCT_INTERRUPT_ENTRY(64)
DISTINCT_INTERRUPT_ENTRY(65)
DISTINCT_INTERRUPT_ENTRY(66)
DISTINCT_INTERRUPT_ENTRY(67)
DISTINCT_INTERRUPT_ENTRY(68)
DISTINCT_INTERRUPT_ENTRY(69)
DISTINCT_INTERRUPT_ENTRY(70)
DISTINCT_INTERRUPT_ENTRY(71)
DISTINCT_INTERRUPT_ENTRY(72)
DISTINCT_INTERRUPT_ENTRY(73)
DISTINCT_INTERRUPT_ENTRY(74)
DISTINCT_INTERRUPT_ENTRY(75)
DISTINCT_INTERRUPT_ENTRY(76)
DISTINCT_INTERRUPT_ENTRY(77)
DISTINCT_INTERRUPT_ENTRY(78)
DISTINCT_INTERRUPT_ENTRY(79)
DISTINCT_INTERRUPT_ENTRY(80)
DISTINCT_INTERRUPT_ENTRY(81)
DISTINCT_INTERRUPT_ENTRY(82)
DISTINCT_INTERRUPT_ENTRY(83)
DISTINCT_INTERRUPT_ENTRY(84)
DISTINCT_INTERRUPT_ENTRY(85)
DISTINCT_INTERRUPT_ENTRY(86)
DISTINCT_INTERRUPT_ENTRY(87)
DISTINCT_INTERRUPT_ENTRY(88)
DISTINCT_INTERRUPT_ENTRY(89)
DISTINCT_INTERRUPT_ENTRY(90)
DISTINCT_INTERRUPT_ENTRY(91)
DISTINCT_INTERRUPT_ENTRY(92)
DISTINCT_INTERRUPT_ENTRY(93)
DISTINCT_INTERRUPT_ENTRY(94)
DISTINCT_INTERRUPT_ENTRY(95)
DISTINCT_INTERRUPT_ENTRY(96)
DISTINCT_INTERRUPT_ENTRY(97)
DISTINCT_INTERRUPT_ENTRY(98)
DISTINCT_INTERRUPT_ENTRY(99)
DISTINCT_INTERRUPT_ENTRY(100)
DISTINCT_INTERRUPT_ENTRY(101)
DISTINCT_INTERRUPT_ENTRY(102)
DISTINCT_INTERRUPT_ENTRY(103)
DISTINCT_INTERRUPT_ENTRY(104)
DISTINCT_INTERRUPT_ENTRY(105)
DISTINCT_INTERRUPT_ENTRY(106)
DISTINCT_INTERRUPT_ENTRY(107)
DISTINCT_INTERRUPT_ENTRY(108)
DISTINCT_INTERRUPT_ENTRY(109)
DISTINCT_INTERRUPT_ENTRY(110)
DISTINCT_INTERRUPT_ENTRY(111)
DISTINCT_INTERRUPT_ENTRY(112)
DISTINCT_INTERRUPT_ENTRY(113)
DISTINCT_INTERRUPT_ENTRY(114)
DISTINCT_INTERRUPT_ENTRY(115)
DISTINCT_INTERRUPT_ENTRY(116)
DISTINCT_INTERRUPT_ENTRY(117)
DISTINCT_INTERRUPT_ENTRY(118)
DISTINCT_INTERRUPT_ENTRY(119)
DISTINCT_INTERRUPT_ENTRY(120)
DISTINCT_INTERRUPT_ENTRY(121)
DISTINCT_INTERRUPT_ENTRY(122)
DISTINCT_INTERRUPT_ENTRY(123)
DISTINCT_INTERRUPT_ENTRY(124)
DISTINCT_INTERRUPT_ENTRY(125)
DISTINCT_INTERRUPT_ENTRY(126)
DISTINCT_INTERRUPT_ENTRY(127)
DISTINCT_INTERRUPT_ENTRY(128)
DISTINCT_INTERRUPT_ENTRY(129)
DISTINCT_INTERRUPT_ENTRY(130)
DISTINCT_INTERRUPT_ENTRY(131)
DISTINCT_INTERRUPT_ENTRY(132)
DISTINCT_INTERRUPT_ENTRY(133)
DISTINCT_INTERRUPT_ENTRY(134)
DISTINCT_INTERRUPT_ENTRY(135)
DISTINCT_INTERRUPT_ENTRY(136)
DISTINCT_INTERRUPT_ENTRY(137)
DISTINCT_INTERRUPT_ENTRY(138)
DISTINCT_INTERRUPT_ENTRY(139)
DISTINCT_INTERRUPT_ENTRY(140)
DISTINCT_INTERRUPT_ENTRY(141)
DISTINCT_INTERRUPT_ENTRY(142)
DISTINCT_INTERRUPT_ENTRY(143)
DISTINCT_INTERRUPT_ENTRY(144)
DISTINCT_INTERRUPT_ENTRY(145)
DISTINCT_INTERRUPT_ENTRY(146)
DISTINCT_INTERRUPT_ENTRY(147)
DISTINCT_INTERRUPT_ENTRY(148)
DISTINCT_INTERRUPT_ENTRY(149)
DISTINCT_INTERRUPT_ENTRY(150)
DISTINCT_INTERRUPT_ENTRY(151)
DISTINCT_INTERRUPT_ENTRY(152)
DISTINCT_INTERRUPT_ENTRY(153)
DISTINCT_INTERRUPT_ENTRY(154)
DISTINCT_INTERRUPT_ENTRY(155)
DISTINCT_INTERRUPT_ENTRY(156)
DISTINCT_INTERRUPT_ENTRY(157)
DISTINCT_INTERRUPT_ENTRY(158)
DISTINCT_INTERRUPT_ENTRY(159)
DISTINCT_INTERRUPT_ENTRY(160)
DISTINCT_INTERRUPT_ENTRY(161)
DISTINCT_INTERRUPT_ENTRY(162)
DISTINCT_INTERRUPT_ENTRY(163)
DISTINCT_INTERRUPT_ENTRY(164)
DISTINCT_INTERRUPT_ENTRY(165)
DISTINCT_INTERRUPT_ENTRY(166)
DISTINCT_INTERRUPT_ENTRY(167)
DISTINCT_INTERRUPT_ENTRY(168)
DISTINCT_INTERRUPT_ENTRY(169)
DISTINCT_INTERRUPT_ENTRY(170)
DISTINCT_INTERRUPT_ENTRY(171)
DISTINCT_INTERRUPT_ENTRY(172)
DISTINCT_INTERRUPT_ENTRY(173)
DISTINCT_INTERRUPT_ENTRY(174)
DISTINCT_INTERRUPT_ENTRY(175)
DISTINCT_INTERRUPT_ENTRY(176)
DISTINCT_INTERRUPT_ENTRY(177)
DISTINCT_INTERRUPT_ENTRY(178)
DISTINCT_INTERRUPT_ENTRY(179)
DISTINCT_INTERRUPT_ENTRY(180)
DISTINCT_INTERRUPT_ENTRY(181)
DISTINCT_INTERRUPT_ENTRY(182)
DISTINCT_INTERRUPT_ENTRY(183)
DISTINCT_INTERRUPT_ENTRY(184)
DISTINCT_INTERRUPT_ENTRY(185)
DISTINCT_INTERRUPT_ENTRY(186)
DISTINCT_INTERRUPT_ENTRY(187)
DISTINCT_INTERRUPT_ENTRY(188)
DISTINCT_INTERRUPT_ENTRY(189)
DISTINCT_INTERRUPT_ENTRY(190)
DISTINCT_INTERRUPT_ENTRY(191)
DISTINCT_INTERRUPT_ENTRY(192)
DISTINCT_INTERRUPT_ENTRY(193)
DISTINCT_INTERRUPT_ENTRY(194)
DISTINCT_INTERRUPT_ENTRY(195)
DISTINCT_INTERRUPT_ENTRY(196)
DISTINCT_INTERRUPT_ENTRY(197)
DISTINCT_INTERRUPT_ENTRY(198)
DISTINCT_INTERRUPT_ENTRY(199)
DISTINCT_INTERRUPT_ENTRY(200)
DISTINCT_INTERRUPT_ENTRY(201)
DISTINCT_INTERRUPT_ENTRY(202)
DISTINCT_INTERRUPT_ENTRY(203)
DISTINCT_INTERRUPT_ENTRY(204)
DISTINCT_INTERRUPT_ENTRY(205)
DISTINCT_INTERRUPT_ENTRY(206)
DISTINCT_INTERRUPT_ENTRY(207)
DISTINCT_INTERRUPT_ENTRY(208)
DISTINCT_INTERRUPT_ENTRY(209)
DISTINCT_INTERRUPT_ENTRY(210)
DISTINCT_INTERRUPT_ENTRY(211)
DISTINCT_INTERRUPT_ENTRY(212)
DISTINCT_INTERRUPT_ENTRY(213)
DISTINCT_INTERRUPT_ENTRY(214)
DISTINCT_INTERRUPT_ENTRY(215)
DISTINCT_INTERRUPT_ENTRY(216)
DISTINCT_INTERRUPT_ENTRY(217)
DISTINCT_INTERRUPT_ENTRY(218)
DISTINCT_INTERRUPT_ENTRY(219)
DISTINCT_INTERRUPT_ENTRY(220)
DISTINCT_INTERRUPT_ENTRY(221)
DISTINCT_INTERRUPT_ENTRY(222)
DISTINCT_INTERRUPT_ENTRY(223)
DISTINCT_INTERRUPT_ENTRY(224)
DISTINCT_INTERRUPT_ENTRY(225)
DISTINCT_INTERRUPT_ENTRY(226)
DISTINCT_INTERRUPT_ENTRY(227)
DISTINCT_INTERRUPT_ENTRY(228)
DISTINCT_INTERRUPT_ENTRY(229)
DISTINCT_INTERRUPT_ENTRY(230)
DISTINCT_INTERRUPT_ENTRY(231)
DISTINCT_INTERRUPT_ENTRY(232)
DISTINCT_INTERRUPT_ENTRY(233)
DISTINCT_INTERRUPT_ENTRY(234)
DISTINCT_INTERRUPT_ENTRY(235)
DISTINCT_INTERRUPT_ENTRY(236)
DISTINCT_INTERRUPT_ENTRY(237)
DISTINCT_INTERRUPT_ENTRY(238)
DISTINCT_INTERRUPT_ENTRY(239)
DISTINCT_INTERRUPT_ENTRY(240)
DISTINCT_INTERRUPT_ENTRY(241)
DISTINCT_INTERRUPT_ENTRY(242)
DISTINCT_INTERRUPT_ENTRY(243)
DISTINCT_INTERRUPT_ENTRY(244)
DISTINCT_INTERRUPT_ENTRY(245)
DISTINCT_INTERRUPT_ENTRY(246)
DISTINCT_INTERRUPT_ENTRY(247)
DISTINCT_INTERRUPT_ENTRY(248)
DISTINCT_INTERRUPT_ENTRY(249)
DISTINCT_INTERRUPT_ENTRY(250)
DISTINCT_INTERRUPT_ENTRY(251)
DISTINCT_INTERRUPT_ENTRY(252)
DISTINCT_INTERRUPT_ENTRY(253)
DISTINCT_INTERRUPT_ENTRY(254)
DISTINCT_INTERRUPT_ENTRY(255)

/*PAGE
 *  void _ISR_Dispatch()
 *
 *  Entry point from the outermost interrupt service routine exit.
 *  The current stack is the supervisor mode stack.
 */

        PUBLIC (_ISR_Dispatch)
SYM (_ISR_Dispatch):

        call      SYM (_Thread_Dispatch)   # invoke Dispatcher

       /*
        * BEGINNING OF DE-ESTABLISH SEGMENTS
        *
        *  NOTE:  Make sure there is code here if code is added to
        *         load the segment registers.
        *
        */

       /***** DE-ESTABLISH SEGMENTS CODE GOES HERE ****/

       /*
        * END OF DE-ESTABLISH SEGMENTS
        */

        popa                                # restore general registers
        iret                                # return to interrupted thread

/*
 *  GO32 does not require these segment related routines.
 */

#ifndef __GO32__
/*PAGE
 *
 *  void i386_Install_idt(
 *    unsigned32 source_offset,
 *    unsigned16 destination_segment,
 *    unsigned32 destination_offset
 *  );
 */

        .p2align  2
        PUBLIC (i386_Install_idt)

.set INSTALL_IDT_SAVED_REGS,   8

.set SOURCE_OFFSET_ARG,        INSTALL_IDT_SAVED_REGS + 4
.set DESTINATION_SEGMENT_ARG,  INSTALL_IDT_SAVED_REGS + 8
.set DESTINATION_OFFSET_ARG,   INSTALL_IDT_SAVED_REGS + 12

SYM (i386_Install_idt):
        push      esi
        push      edi

        movl      SOURCE_OFFSET_ARG(esp),esi
        movl      DESTINATION_OFFSET_ARG(esp),edi

        pushf                                  # save flags
        cli                                    # DISABLE INTERRUPTS!!!

        movw      DESTINATION_SEGMENT_ARG+4(esp),ax
        push      es                           # save es
        movw      ax,es
        movsl                                  # copy 1st half of IDT entry
        movsl                                  # copy 2nd half of IDT entry
        pop       es                           # restore es

        popf                                   # ENABLE INTERRUPTS!!!

        pop       edi
        pop       esi
        ret

/*
 *  void *i386_Logical_to_physical(
 *     rtems_unsigned16  segment,
 *     void             *address
 *  );
 *
 *  Returns thirty-two bit physical address for segment:address.
 */

.set SEGMENT_ARG, 4
.set ADDRESS_ARG, 8

             PUBLIC (i386_Logical_to_physical)

SYM (i386_Logical_to_physical):

        xorl    eax,eax                # clear eax
        movzwl  SEGMENT_ARG(esp),ecx   # ecx = segment value
        movl    $ SYM (_Global_descriptor_table),edx
                                       # edx = address of our GDT
        addl    ecx,edx                # edx = address of desired entry
        movb    7(edx),ah              # ah = base 31:24
        movb    4(edx),al              # al = base 23:16
        shll    $16,eax                # move ax into correct bits
        movw    2(edx),ax              # ax = base 0:15
        movl    ADDRESS_ARG(esp),ecx   # ecx = address to convert
        addl    eax,ecx                # ecx = physical address equivalent
        movl    ecx,eax                # eax = ecx
        ret

/*
 *  void *i386_Physical_to_logical(
 *     rtems_unsigned16  segment,
 *     void             *address
 *  );
 *
 *  Returns thirty-two bit physical address for segment:address.
 */

/*
 *.set SEGMENT_ARG, 4
 *.set ADDRESS_ARG, 8   -- use sets from above
 */

       PUBLIC (i386_Physical_to_logical)

SYM (i386_Physical_to_logical):
        xorl    eax,eax                # clear eax
        movzwl  SEGMENT_ARG(esp),ecx   # ecx = segment value
        movl    $ SYM (_Global_descriptor_table),edx
                                       # edx = address of our GDT
        addl    ecx,edx                # edx = address of desired entry
        movb    7(edx),ah              # ah = base 31:24
        movb    4(edx),al              # al = base 23:16
        shll    $16,eax                # move ax into correct bits
        movw    2(edx),ax              # ax = base 0:15
        movl    ADDRESS_ARG(esp),ecx   # ecx = address to convert
        subl    eax,ecx                # ecx = logical address equivalent
        movl    ecx,eax                # eax = ecx
        ret
#endif /* __GO32__ */

END_CODE

END