Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
cmucl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Carl Shapiro
cmucl
Commits
a1230ec0
Commit
a1230ec0
authored
20 years ago
by
cwang
Browse files
Options
Downloads
Patches
Plain Diff
This file is quite similar to x86-arch.c
parent
617e53e5
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
lisp/amd64-arch.c
+420
-0
420 additions, 0 deletions
lisp/amd64-arch.c
with
420 additions
and
0 deletions
lisp/amd64-arch.c
0 → 100644
+
420
−
0
View file @
a1230ec0
/* x86-arch.c -*- Mode: C; comment-column: 40 -*-
*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/amd64-arch.c,v 1.1 2004/05/18 21:53:56 cwang Exp $
*
*/
#include
<stdio.h>
#include
"lisp.h"
#include
"globals.h"
#include
"validate.h"
#include
"os.h"
#include
"internals.h"
#include
"arch.h"
#include
"lispregs.h"
#include
"signal.h"
#include
"alloc.h"
#include
"interrupt.h"
#include
"interr.h"
#include
"breakpoint.h"
#define DPRINTF(test, e) {if(test) fprintf e ;}
#define BREAKPOINT_INST 0xcc
/* INT3 */
unsigned
long
fast_random_state
=
1
;
char
*
arch_init
(
void
)
{
return
"lisp.core"
;
}
/*
* Assuming we get here via an INT3 xxx instruction, the PC now
* points to the interrupt code (lisp value) so we just move past
* it. Skip the code, then if the code is an error-trap or
* Cerror-trap then skip the data bytes that follow.
*/
void
arch_skip_instruction
(
struct
sigcontext
*
context
)
{
int
vlen
,
code
;
DPRINTF
(
0
,(
stderr
,
"[arch_skip_inst at %x>]
\n
"
,
context
->
sc_pc
));
/* Get and skip the lisp error code. */
code
=
*
(
char
*
)
context
->
sc_pc
++
;
switch
(
code
)
{
case
trap_Error
:
case
trap_Cerror
:
/* Lisp error arg vector length */
vlen
=
*
(
char
*
)
context
->
sc_pc
++
;
/* Skip lisp error arg data bytes */
while
(
vlen
--
>
0
)
((
char
*
)
context
->
sc_pc
)
++
;
break
;
case
trap_Breakpoint
:
case
trap_FunctionEndBreakpoint
:
break
;
case
trap_PendingInterrupt
:
case
trap_Halt
:
/* Only needed to skip the Code. */
break
;
default:
fprintf
(
stderr
,
"[arch_skip_inst invalid code %d
\n
]
\n
"
,
code
);
break
;
}
DPRINTF
(
0
,(
stderr
,
"[arch_skip_inst resuming at %x>]
\n
"
,
context
->
sc_pc
));
}
unsigned
char
*
arch_internal_error_arguments
(
struct
sigcontext
*
context
)
{
return
(
unsigned
char
*
)
(
context
->
sc_pc
+
1
);
}
boolean
arch_pseudo_atomic_atomic
(
struct
sigcontext
*
context
)
{
return
SymbolValue
(
PSEUDO_ATOMIC_ATOMIC
);
}
void
arch_set_pseudo_atomic_interrupted
(
struct
sigcontext
*
context
)
{
SetSymbolValue
(
PSEUDO_ATOMIC_INTERRUPTED
,
make_fixnum
(
1
));
}
unsigned
long
arch_install_breakpoint
(
void
*
pc
)
{
unsigned
long
result
=
*
(
unsigned
long
*
)
pc
;
*
(
char
*
)
pc
=
BREAKPOINT_INST
;
/* x86 INT3 */
*
((
char
*
)
pc
+
1
)
=
trap_Breakpoint
;
/* Lisp trap code */
return
result
;
}
void
arch_remove_breakpoint
(
void
*
pc
,
unsigned
long
orig_inst
)
{
*
((
char
*
)
pc
)
=
orig_inst
&
0xff
;
*
((
char
*
)
pc
+
1
)
=
(
orig_inst
&
0xff00
)
>>
8
;
}
/*
* When single stepping single_stepping holds the original instruction
* pc location.
*/
unsigned
int
*
single_stepping
=
NULL
;
#ifndef __linux__
unsigned
int
single_step_save1
;
unsigned
int
single_step_save2
;
unsigned
int
single_step_save3
;
#endif
void
arch_do_displaced_inst
(
struct
sigcontext
*
context
,
unsigned
long
orig_inst
)
{
unsigned
int
*
pc
=
(
unsigned
int
*
)
context
->
sc_pc
;
/*
* Put the original instruction back.
*/
*
((
char
*
)
pc
)
=
orig_inst
&
0xff
;
*
((
char
*
)
pc
+
1
)
=
(
orig_inst
&
0xff00
)
>>
8
;
#ifdef __linux__
context
->
eflags
|=
0x100
;
#else
/*
* Install helper instructions for the single step:
* pushf; or [esp],0x100; popf.
*/
single_step_save1
=
*
(
pc
-
3
);
single_step_save2
=
*
(
pc
-
2
);
single_step_save3
=
*
(
pc
-
1
);
*
(
pc
-
3
)
=
0x9c909090
;
*
(
pc
-
2
)
=
0x00240c81
;
*
(
pc
-
1
)
=
0x9d000001
;
#endif
single_stepping
=
(
unsigned
int
*
)
pc
;
#ifndef __linux__
(
unsigned
int
*
)
context
->
sc_pc
=
(
char
*
)
pc
-
9
;
#endif
}
void
sigtrap_handler
(
HANDLER_ARGS
)
{
unsigned
int
trap
;
#ifdef __linux__
GET_CONTEXT
#endif
#if 0
fprintf(stderr,"x86sigtrap: %8x %x\n",
context->sc_pc, *(unsigned char *)(context->sc_pc-1));
fprintf(stderr,"sigtrap(%d %d %x)\n",signal,code,context);
#endif
if
(
single_stepping
&&
(
signal
==
SIGTRAP
))
{
#if 0
fprintf(stderr,"* Single step trap %x\n", single_stepping);
#endif
#ifndef __linux__
/* Un-install single step helper instructions. */
*
(
single_stepping
-
3
)
=
single_step_save1
;
*
(
single_stepping
-
2
)
=
single_step_save2
;
*
(
single_stepping
-
1
)
=
single_step_save3
;
#else
context
->
eflags
^=
0x100
;
#endif
/*
* Re-install the breakpoint if possible.
*/
if
((
int
)
context
->
sc_pc
==
(
int
)
single_stepping
+
1
)
fprintf
(
stderr
,
"* Breakpoint not re-install
\n
"
);
else
{
char
*
ptr
=
(
char
*
)
single_stepping
;
ptr
[
0
]
=
BREAKPOINT_INST
;
/* x86 INT3 */
ptr
[
1
]
=
trap_Breakpoint
;
}
single_stepping
=
NULL
;
return
;
}
SAVE_CONTEXT
();
/* This is just for info in case monitor wants to print an approx */
current_control_stack_pointer
=
(
unsigned
long
*
)
context
->
sc_sp
;
#if defined(__linux__) && (defined(i386) || defined(__x86_64))
/*
* Restore the FPU control word, setting the rounding mode to nearest.
*/
if
(
contextstruct
.
fpstate
)
#if defined(__x86_64)
setfpucw
(
contextstruct
.
fpstate
->
cwd
&
~
0xc00
);
#else
setfpucw
(
contextstruct
.
fpstate
->
cw
&
~
0xc00
);
#endif
#endif
/*
* On entry %eip points just after the INT3 byte and aims at the
* 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
* number of bytes will follow, the first is the length of the byte
* arguments to follow.
*/
trap
=
*
(
unsigned
char
*
)
(
context
->
sc_pc
);
switch
(
trap
)
{
case
trap_PendingInterrupt
:
DPRINTF
(
0
,(
stderr
,
"<trap Pending Interrupt.>
\n
"
));
arch_skip_instruction
(
context
);
interrupt_handle_pending
(
context
);
break
;
case
trap_Halt
:
{
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
int
fpu_state
[
27
];
fpu_save
(
fpu_state
);
#endif
fake_foreign_function_call
(
context
);
lose
(
"%%primitive halt called; the party is over.
\n
"
);
undo_fake_foreign_function_call
(
context
);
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
fpu_restore
(
fpu_state
);
#endif
arch_skip_instruction
(
context
);
break
;
}
case
trap_Error
:
case
trap_Cerror
:
DPRINTF
(
0
,
(
stderr
,
"<trap Error %d>
\n
"
,
code
));
#ifdef __linux__
interrupt_internal_error
(
signal
,
contextstruct
,
code
==
trap_Cerror
);
#else
interrupt_internal_error
(
signal
,
code
,
context
,
code
==
trap_Cerror
);
#endif
break
;
case
trap_Breakpoint
:
#if 0
fprintf(stderr,"*C break\n");
#endif
(
char
*
)
context
->
sc_pc
-=
1
;
handle_breakpoint
(
signal
,
code
,
context
);
#if 0
fprintf(stderr,"*C break return\n");
#endif
break
;
case
trap_FunctionEndBreakpoint
:
(
char
*
)
context
->
sc_pc
-=
1
;
context
->
sc_pc
=
(
int
)
handle_function_end_breakpoint
(
signal
,
code
,
context
);
break
;
#ifdef trap_DynamicSpaceOverflowWarning
case
trap_DynamicSpaceOverflowWarning
:
interrupt_handle_space_overflow
(
SymbolFunction
(
DYNAMIC_SPACE_OVERFLOW_WARNING_HIT
),
context
);
break
;
#endif
#ifdef trap_DynamicSpaceOverflowError
case
trap_DynamicSpaceOverflowError
:
interrupt_handle_space_overflow
(
SymbolFunction
(
DYNAMIC_SPACE_OVERFLOW_ERROR_HIT
),
context
);
break
;
#endif
default:
DPRINTF
(
0
,(
stderr
,
"[C--trap default %d %d %x]
\n
"
,
signal
,
code
,
context
));
#ifdef __linux__
interrupt_handle_now
(
signal
,
contextstruct
);
#else
interrupt_handle_now
(
signal
,
code
,
context
);
#endif
break
;
}
}
#define FIXNUM_VALUE(lispobj) (((int) lispobj) >> 2)
void
arch_install_interrupt_handlers
()
{
interrupt_install_low_level_handler
(
SIGILL
,
sigtrap_handler
);
interrupt_install_low_level_handler
(
SIGTRAP
,
sigtrap_handler
);
}
extern
lispobj
call_into_lisp
(
lispobj
fun
,
lispobj
*
args
,
int
nargs
);
/* These next four functions are an interface to the
* Lisp call-in facility. Since this is C we can know
* nothing about the calling environment. The control
* stack might be the C stack if called from the monitor
* or the Lisp stack if called as a result of an interrupt
* or maybe even a separate stack. The args are most likely
* on that stack but could be in registers depending on
* what the compiler likes. So I try to package up the
* args into a portable vector and let the assembly language
* call-in function figure it out.
*/
lispobj
funcall0
(
lispobj
function
)
{
lispobj
*
args
=
NULL
;
return
call_into_lisp
(
function
,
args
,
0
);
}
lispobj
funcall1
(
lispobj
function
,
lispobj
arg0
)
{
lispobj
args
[
1
];
args
[
0
]
=
arg0
;
return
call_into_lisp
(
function
,
args
,
1
);
}
lispobj
funcall2
(
lispobj
function
,
lispobj
arg0
,
lispobj
arg1
)
{
lispobj
args
[
2
];
args
[
0
]
=
arg0
;
args
[
1
]
=
arg1
;
return
call_into_lisp
(
function
,
args
,
2
);
}
lispobj
funcall3
(
lispobj
function
,
lispobj
arg0
,
lispobj
arg1
,
lispobj
arg2
)
{
lispobj
args
[
3
];
args
[
0
]
=
arg0
;
args
[
1
]
=
arg1
;
args
[
2
]
=
arg2
;
return
call_into_lisp
(
function
,
args
,
3
);
}
#ifdef LINKAGE_TABLE
#ifndef LinkageEntrySize
#define LinkageEntrySize 16
#endif
void
arch_make_linkage_entry
(
long
linkage_entry
,
void
*
target_addr
,
long
type
)
{
char
*
reloc_addr
=
(
char
*
)(
FOREIGN_LINKAGE_SPACE_START
+
linkage_entry
*
LinkageEntrySize
);
if
(
type
==
1
)
{
/* code reference */
/* Make JMP to function entry. */
long
offset
=
(
char
*
)
target_addr
;
int
i
;
*
reloc_addr
++
=
0x49
;
/* opcode for MOV */
*
reloc_addr
++
=
0xbf
;
/* %r15 */
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
reloc_addr
++
=
offset
&
0xff
;
offset
>>=
8
;
}
*
reloc_addr
++
=
0x41
;
/* jmpq */
*
reloc_addr
++
=
0xff
;
*
reloc_addr
++
=
0xe7
;
/* %r15 */
/* write a nop for good measure. */
*
reloc_addr
=
0x90
;
}
else
if
(
type
==
2
)
{
*
(
unsigned
long
*
)
reloc_addr
=
(
unsigned
long
)
target_addr
;
}
}
/* Make a call to the first function in the linkage table, which is
resolve_linkage_tramp. */
void
arch_make_lazy_linkage
(
long
linkage_entry
)
{
char
*
reloc_addr
=
(
char
*
)(
FOREIGN_LINKAGE_SPACE_START
+
linkage_entry
*
LinkageEntrySize
);
long
offset
=
(
char
*
)(
FOREIGN_LINKAGE_SPACE_START
)
-
(
reloc_addr
+
5
);
int
i
;
*
reloc_addr
++
=
0xe8
;
/* opcode for CALL rel32 */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
*
reloc_addr
++
=
offset
&
0xff
;
offset
>>=
8
;
}
/* write a nop for good measure. */
*
reloc_addr
=
0x90
;
}
/* Get linkage entry. The initial instruction in the linkage
entry is a CALL; the return address we're passed points to the next
instruction. */
long
arch_linkage_entry
(
unsigned
long
retaddr
)
{
return
((
retaddr
-
5
)
-
FOREIGN_LINKAGE_SPACE_START
)
/
LinkageEntrySize
;
}
#endif
/* LINKAGE_TABLE */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment