summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/i386/idtr.S
blob: b77bd146e07d58b076222a72ea4f1f63e9e96beb (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
/*  cpu_asm.S
 *
 *  This file contains all assembly code for the Intel i386 IDT
 *  manipulation.
 *
 *  COPYRIGHT (c) 1998 valette@crf.canon.fr
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#include <rtems/asm.h>

BEGIN_CODE
/*
 * C callable function enabling to get easilly usable info from
 * the actual value of IDT register.
 *
extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
				     unsigned* limit);
 */
PUBLIC (i386_get_info_from_IDTR)
PUBLIC (i386_set_IDTR)
PUBLIC (i386_get_info_from_GDTR)
PUBLIC (i386_set_GDTR)

SYM (i386_get_info_from_IDTR):
	movl	4(esp), ecx	    /* get location where table address */
                                    /*    must be stored */
	movl	8(esp), edx	    /* get location table size must be stored */

	subl	$6, esp		    /* let room to prepare 48 bit IDTR */

	sidt	(esp)		    /* get 48 bit IDTR value */

	movl	2(esp), eax	    /* get base */
	movl	eax, (ecx)

	movzwl	(esp), eax	    /* get limit */
	movl	eax, (edx)

	addl	$6, esp		    /* restore %esp */
	ret

/*
 * C callable function enabling to change the value of IDT register. Must be called
 * with inmterrupt masked at processor level!!!.
 *
extern void i386_set_IDTR (interrupt_gate_descriptor* table,
		           unsigned limit);
 */
SYM (i386_set_IDTR):

	leal	4(esp), edx	    /* load in edx address of input */
                                    /*    parameter "table" */

	movl	(edx), eax	    /* load base into eax */
	movl	4(edx), ecx	    /* load limit into ecx */

	movw	cx, (edx)	    /* prepare 48 bit pointer */
	movl	eax, 2(edx)

	lidt	(edx)

	ret
/*
 *
 * C callable function enabling to get easilly usable info from
 * the actual value of GDT register.
extern void i386_get_info_from_GDTR (segment_descriptors** table,
				     unsigned* limit);
 */

SYM (i386_get_info_from_GDTR):
	movl	4(esp), ecx	    /* get location where table address */
                                    /*    must be stored */
	movl	8(esp), edx	    /* get location table size must be stored */

	subl	$6, esp		    /* let room to prepare 48 bit GDTR */

	sgdt	(esp)		    /* get 48 bit GDTR value */

	movl	2(esp), eax	    /* get base */
	movl	eax, (ecx)

	movzwl	(esp), eax	    /* get limit */
	movl	eax, (edx)

	addl	$6, esp		    /* restore %esp */
	ret

/*
 * C callable function enabling to change the value of GDT register.
 * Must be called with interrupts masked at processor level!!!.
 *   extern void i386_set_GDTR (segment_descriptors*, unsigned limit);
 */
SYM (i386_set_GDTR):

	leal	4(esp), edx	    /* load in edx address of input */
                                    /*   parameter "table" */

	movl	(edx), eax	    /* load base into eax */
	movl	4(edx), ecx	    /* load limit into ecx */

	movw	cx, (edx)	    /* prepare 48 bit pointer */
	movl	eax, 2(edx)

	lgdt	(edx)

	ret

END_CODE

END