/* cpu_asm.s
*
* This file contains all assembly code for the Intel i386 implementation
* of RTEMS.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
* All rights assigned to U.S. Government, 1994.
*
* This material may be reproduced by or for the U.S. Government pursuant
* to the copyright license under the clause at DFARS 252.227-7013. This
* notice must appear in all copies of this file and its derivatives.
*
* $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.
*/
.align 2
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
.align 2
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
.align 2
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
.align 2
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) \
.align 16 ; \
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
/*PAGE
*
* void i386_Install_idt(
* unsigned32 source_offset,
* unsigned16 destination_segment,
* unsigned32 destination_offset
* );
*/
.align 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
END_CODE
END