stackslots.
* src/vm/jit/tools/genoffsets.c (main): Offsets of intregs and fltregs.
* src/vm/jit/i386/asmpart.S (asm_replacement_out): Renamed regs to
intregs. Some cleanup.
* src/vm/jit/replace.c (replace_activate_replacement_point)
(replace_deactivate_replacement_point): Enabled on x86_64.
(replace_read_executionstate, replace_write_executionstate):
Deal with 4/8-byte stackslots. Handle float registers.
(replace_executionstate_println, replace_sourcestate_println):
Print register names where possible.
* src/vm/jit/x86_64/md.c (md_patch_replacement_point): Added.
(vim boilerplate): Added.
* src/vm/jit/x86_64/codegen.c (codegen): Handle replacement points.
Generate replacement-out stubs.
* src/vm/jit/x86_64/asmpart.S (asm_replacement_out, asm_replacement_in):
Added.
(vim boilerplate): Added.
* src/vm/jit/replace.h (executionstate): Separate registers into int
and float registers. Some cleanup, use INT_REG_CNT, FLT_REG_CNT macros.
#include "vm/jit/code.h"
#include "mm/memory.h"
#include "vm/options.h"
+#include "arch.h"
codeinfo *code_codeinfo_new(methodinfo *m)
{
assert(code);
- /* XXX adapt for 4/8 byte stackslots */
-
+ /* XXX generalize to all archs */
+#ifdef HAS_4BYTE_STACKSLOT
count = code->memuse + code->savedintcount + 2*code->savedfltcount;
+#else
+ count = code->memuse + code->savedintcount + code->savedfltcount;
+#endif
+ /* XXX generalize to all archs */
if (checksync && (code->m->flags & ACC_SYNCHRONIZED))
+#ifdef HAS_4BYTE_STACKSLOT
count += (IS_2_WORD_TYPE(code->m->parseddesc->returntype.type)) ? 2 : 1;
+#else
+ count++;
+#endif
return count;
}
Changes: Joseph Wenninger
Edwin Steiner
- $Id: asmpart.S 4618 2006-03-15 20:40:57Z edwin $
+ $Id: asmpart.S 4623 2006-03-16 00:05:18Z edwin $
*/
.globl asm_handle_exception
.globl asm_wrapper_patcher
+
.globl asm_replacement_out
.globl asm_replacement_in
sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
/* save registers in execution state */
- mov %eax,(EAX*8+offes_regs)(sp)
- mov %ebx,(EBX*8+offes_regs)(sp)
- mov %ecx,(ECX*8+offes_regs)(sp)
- mov %edx,(EDX*8+offes_regs)(sp)
- mov %esi,(ESI*8+offes_regs)(sp)
- mov %edi,(EDI*8+offes_regs)(sp)
- mov %ebp,(EBP*8+offes_regs)(sp)
- movl $0 ,(ESP*8+offes_regs)(sp) /* XXX */
+ mov %eax,(EAX*8+offes_intregs)(sp)
+ mov %ebx,(EBX*8+offes_intregs)(sp)
+ mov %ecx,(ECX*8+offes_intregs)(sp)
+ mov %edx,(EDX*8+offes_intregs)(sp)
+ mov %esi,(ESI*8+offes_intregs)(sp)
+ mov %edi,(EDI*8+offes_intregs)(sp)
+ mov %ebp,(EBP*8+offes_intregs)(sp)
+ movl $0 ,(ESP*8+offes_intregs)(sp) /* not used */
#ifndef NDEBUG
/* clear high 32bit */
- movl $0,(4+0*8+offes_regs)(sp)
- movl $0,(4+1*8+offes_regs)(sp)
- movl $0,(4+2*8+offes_regs)(sp)
- movl $0,(4+3*8+offes_regs)(sp)
- movl $0,(4+4*8+offes_regs)(sp)
- movl $0,(4+5*8+offes_regs)(sp)
- movl $0,(4+6*8+offes_regs)(sp)
- movl $0,(4+7*8+offes_regs)(sp)
+ movl $0,(4+0*8+offes_intregs)(sp)
+ movl $0,(4+1*8+offes_intregs)(sp)
+ movl $0,(4+2*8+offes_intregs)(sp)
+ movl $0,(4+3*8+offes_intregs)(sp)
+ movl $0,(4+4*8+offes_intregs)(sp)
+ movl $0,(4+5*8+offes_intregs)(sp)
+ movl $0,(4+6*8+offes_intregs)(sp)
+ movl $0,(4+7*8+offes_intregs)(sp)
#endif
/* calculate sp of method */
*******************************************************************************/
asm_replacement_in:
- mov %esp,%ebp /* save stackptr */
-
- mov (4+0)(%ebp),%ebp /* executionstate *es */
+ mov 4(sp),%ebp /* executionstate *es */
/* set new sp */
mov (offes_sp)(%ebp),%esp
push (offes_pc)(%ebp)
/* copy registers from execution state */
- mov (EAX*8+offes_regs)(%ebp),%eax
- mov (EBX*8+offes_regs)(%ebp),%ebx
- mov (ECX*8+offes_regs)(%ebp),%ecx
- mov (EDX*8+offes_regs)(%ebp),%edx
- mov (ESI*8+offes_regs)(%ebp),%esi
- mov (EDI*8+offes_regs)(%ebp),%edi
- mov (EBP*8+offes_regs)(%ebp),%ebp
+ mov (EAX*8+offes_intregs)(%ebp),%eax
+ mov (EBX*8+offes_intregs)(%ebp),%ebx
+ mov (ECX*8+offes_intregs)(%ebp),%ecx
+ mov (EDX*8+offes_intregs)(%ebp),%edx
+ mov (ESI*8+offes_intregs)(%ebp),%esi
+ mov (EDI*8+offes_intregs)(%ebp),%edi
+
+ mov (EBP*8+offes_intregs)(%ebp),%ebp
/* jump to new code */
ret
#include "vm/options.h"
#include "vm/jit/replace.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
+#include "arch.h"
/* replace_create_replacement_points *******************************************
rp->target = target;
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
md_patch_replacement_point(rp);
#endif
}
rp->target = NULL;
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
md_patch_replacement_point(rp);
#endif
}
int t;
int allocs;
rplalloc *ra;
- u4 *sp; /* XXX configure stack slot size */
- u4 *basesp;
methoddesc *md;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+ u4 *basesp;
+#else
+ u8 *sp;
+ u8 *basesp;
+#endif
code = rp->code;
m = code->m;
/* calculate stack pointers */
+#ifdef HAS_4BYTE_STACKSLOT
sp = (u4*) es->sp;
+#else
+ sp = (u8*) es->sp;
+#endif
basesp = sp + code_get_stack_frame_size(code);
/* read local variables */
ss->javalocals[i*5+t] = sp[ra->index];
}
else {
- ss->javalocals[i*5+t] = es->regs[ra->index];
+ ss->javalocals[i*5+t] = es->intregs[ra->index];
}
}
ss->javastack[i] = sp[ra->index];
}
else {
- ss->javastack[i] = es->regs[ra->index];
+ ss->javastack[i] = es->intregs[ra->index];
}
}
for (i=0; count > code->savedintcount; ++i) {
assert(i < INT_REG_CNT);
if (nregdescint[i] == REG_SAV)
- ss->savedintregs[--count] = es->regs[i];
+ ss->savedintregs[--count] = es->intregs[i];
}
/* read saved int regs */
/* read saved flt regs */
for (i=0; i<code->savedfltcount; ++i) {
+#ifdef HAS_4BYTE_STACKSLOT
basesp -= 2;
+#else
+ basesp--;
+#endif
ss->savedfltregs[i] = *(u8*)basesp;
}
-#ifndef NDEBUG
- /* XXX */
- for (; i<FLT_SAV_CNT; ++i)
- ss->savedfltregs[i] = (u8) 0x00dead0000dead00ULL;
-#endif
+
+ /* read unused callee saved flt regs */
+
+ count = FLT_SAV_CNT;
+ for (i=0; count > code->savedfltcount; ++i) {
+ assert(i < FLT_REG_CNT);
+ if (nregdescfloat[i] == REG_SAV)
+ ss->savedfltregs[--count] = es->fltregs[i];
+ }
}
/* replace_write_executionstate ************************************************
int t;
int allocs;
rplalloc *ra;
- u4 *sp; /* XXX configure stack slot size */
- u4 *basesp; /* XXX configure stack slot size */
methoddesc *md;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+ u4 *basesp;
+#else
+ u8 *sp;
+ u8 *basesp;
+#endif
code = rp->code;
m = code->m;
/* calculate stack pointers */
+#ifdef HAS_4BYTE_STACKSLOT
sp = (u4*) es->sp;
+#else
+ sp = (u8*) es->sp;
+#endif
basesp = sp + code_get_stack_frame_size(code);
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- basesp += (IS_2_WORD_TYPE(md->returntype.type)) ? 2 : 1;
-
/* in debug mode, invalidate stack frame first */
#ifndef NDEBUG
sp[ra->index] = ss->javalocals[i*5+t];
}
else {
- es->regs[ra->index] = ss->javalocals[i*5+t];
+ es->intregs[ra->index] = ss->javalocals[i*5+t];
}
}
sp[ra->index] = ss->javastack[i];
}
else {
- es->regs[ra->index] = ss->javastack[i];
+ es->intregs[ra->index] = ss->javastack[i];
}
}
for (i=0; count > code->savedintcount; ++i) {
assert(i < INT_REG_CNT);
if (nregdescint[i] == REG_SAV)
- es->regs[i] = ss->savedintregs[--count];
+ es->intregs[i] = ss->savedintregs[--count];
}
/* write saved int regs */
*--basesp = ss->savedintregs[i];
}
+ /* write unused callee saved flt regs */
+
+ count = FLT_SAV_CNT;
+ for (i=0; count > code->savedfltcount; ++i) {
+ assert(i < FLT_REG_CNT);
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = ss->savedfltregs[--count];
+ }
+
/* write saved flt regs */
for (i=0; i<code->savedfltcount; ++i) {
+#ifdef HAS_4BYTE_STACKSLOT
basesp -= 2;
+#else
+ basesp--;
+#endif
*(u8*)basesp = ss->savedfltregs[i];
}
/* enter new code */
-#if defined(__I386__) && defined(ENABLE_JIT)
+#if (defined(__I386__) || defined(__X86_64__)) && defined(ENABLE_JIT)
asm_replacement_in(es);
#endif
abort();
void replace_executionstate_println(executionstate *es,codeinfo *code)
{
int i;
- u4 *slotptr; /* XXX configure stack slot size */
int slots;
+#ifdef HAS_4BYTE_STACKSLOT
+ u4 *sp;
+#else
+ u8 *sp;
+#endif
if (!es) {
printf("(executionstate *)NULL\n");
printf("executionstate %p:\n",(void*)es);
printf("\tpc = %p\n",(void*)es->pc);
printf("\tsp = %p\n",(void*)es->sp);
- for (i=0; i<MD_EXCSTATE_NREGS; ++i) {
- printf("\tregs[%2d] = %016llx\n",i,(unsigned long long)es->regs[i]);
+ for (i=0; i<INT_REG_CNT; ++i) {
+ printf("\t%-3s = %016llx\n",regs[i],(unsigned long long)es->intregs[i]);
+ }
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ printf("\tfltregs[%2d] = %016llx\n",i,(unsigned long long)es->fltregs[i]);
}
- slotptr = (u4*) es->sp;
+#ifdef HAS_4BYTE_STACKSLOT
+ sp = (u4*) es->sp;
+#else
+ sp = (u8*) es->sp;
+#endif
if (code)
slots = code_get_stack_frame_size(code);
printf("\tstack slots at sp:\n");
for (i=0; i<slots; ++i) {
- printf("\t\t%08lx\n",(unsigned long)*slotptr++);
+#ifdef HAS_4BYTE_STACKSLOT
+ printf("\t\t%08lx\n",(unsigned long)*sp++);
+#else
+ printf("\t\t%016llx\n",(unsigned long long)*sp++);
+#endif
}
printf("\n");
{
int i;
int t;
+ int reg;
if (!ss) {
printf("(sourcestate *)NULL\n");
printf("\n");
printf("\tsaved int registers (%d):\n",INT_SAV_CNT);
+ reg = INT_REG_CNT;
for (i=0; i<INT_SAV_CNT; ++i) {
+ while (nregdescint[--reg] != REG_SAV)
+ ;
if (ss->savedintregs[i] != 0x00dead0000dead00ULL) {
- printf("\tsavedintreg[%2d] = ",i);
+ printf("\t%-3s = ",regs[reg]);
printf("%016llx\n",(unsigned long long) ss->savedintregs[i]);
}
}
/* An `executionsstate` represents the state of a thread as it reached */
/* an replacement point or is about to enter one. */
-#define MD_EXCSTATE_NREGS (8)
-#define MD_EXCSTATE_INT_NSAVED 3
-#define MD_EXCSTATE_FLT_NSAVED 0
-
struct executionstate {
u1 *pc; /* program counter */
u1 *sp; /* stack pointer within method */
- u8 regs[MD_EXCSTATE_NREGS]; /* register values */
+ u8 intregs[INT_REG_CNT]; /* register values */
+ u8 fltregs[FLT_REG_CNT]; /* register values */
};
/* `sourcestate` will probably only be used for debugging */
Changes: Edwin Steiner
- $Id: genoffsets.c 4617 2006-03-15 20:38:30Z edwin $
+ $Id: genoffsets.c 4623 2006-03-16 00:05:18Z edwin $
*/
printf("#define offes_pc %3d\n", (s4) OFFSET(executionstate, pc));
printf("#define offes_sp %3d\n", (s4) OFFSET(executionstate, sp));
- printf("#define offes_regs %3d\n", (s4) OFFSET(executionstate, regs));
+ printf("#define offes_intregs %3d\n", (s4) OFFSET(executionstate, intregs));
+ printf("#define offes_fltregs %3d\n", (s4) OFFSET(executionstate, fltregs));
/* everything is ok */
Reinhard Grafl
Christian Thalinger
- Changes:
+ Changes: Edwin Steiner
- $Id: asmpart.S 4559 2006-03-05 23:24:50Z twisti $
+ $Id: asmpart.S 4623 2006-03-16 00:05:18Z edwin $
*/
.globl asm_wrapper_patcher
+ .globl asm_replacement_out
+ .globl asm_replacement_in
+
.globl asm_builtin_f2i
.globl asm_builtin_f2l
.globl asm_builtin_d2i
jmp L_asm_handle_exception
+/* asm_replacement_out *********************************************************
+
+ This code is jumped to from the replacement-out stubs that are executed
+ when a thread reaches an activated replacement point.
+
+ The purpose of asm_replacement_out is to read out the parts of the
+ execution state that cannot be accessed from C code, store this state,
+ and then call the C function replace_me.
+
+ Stack layout:
+ 8 start of stack inside method to replace
+ 0 rplpoint * info on the replacement point that was reached
+
+*******************************************************************************/
+
+/* some room to accomodate changes of the stack frame size during replacement */
+ /* XXX we should find a cleaner solution here */
+#define REPLACEMENT_ROOM 512
+
+asm_replacement_out:
+ /* create stack frame */
+ sub $(sizeexecutionstate + REPLACEMENT_ROOM),sp
+
+ /* save registers in execution state */
+ mov %rax,(RAX*8+offes_intregs)(sp)
+ mov %rbx,(RBX*8+offes_intregs)(sp)
+ mov %rcx,(RCX*8+offes_intregs)(sp)
+ mov %rdx,(RDX*8+offes_intregs)(sp)
+ mov %rsi,(RSI*8+offes_intregs)(sp)
+ mov %rdi,(RDI*8+offes_intregs)(sp)
+ mov %rbp,(RBP*8+offes_intregs)(sp)
+ movq $0 ,(RSP*8+offes_intregs)(sp) /* not used */
+ mov %r8 ,(R8 *8+offes_intregs)(sp)
+ mov %r9 ,(R9 *8+offes_intregs)(sp)
+ mov %r10,(R10*8+offes_intregs)(sp)
+ mov %r11,(R11*8+offes_intregs)(sp)
+ mov %r12,(R12*8+offes_intregs)(sp)
+ mov %r13,(R13*8+offes_intregs)(sp)
+ mov %r14,(R14*8+offes_intregs)(sp)
+ mov %r15,(R15*8+offes_intregs)(sp)
+
+ movq %xmm0 ,(XMM0 *8+offes_fltregs)(sp)
+ movq %xmm1 ,(XMM1 *8+offes_fltregs)(sp)
+ movq %xmm2 ,(XMM2 *8+offes_fltregs)(sp)
+ movq %xmm3 ,(XMM3 *8+offes_fltregs)(sp)
+ movq %xmm4 ,(XMM4 *8+offes_fltregs)(sp)
+ movq %xmm5 ,(XMM5 *8+offes_fltregs)(sp)
+ movq %xmm6 ,(XMM6 *8+offes_fltregs)(sp)
+ movq %xmm7 ,(XMM7 *8+offes_fltregs)(sp)
+ movq %xmm8 ,(XMM8 *8+offes_fltregs)(sp)
+ movq %xmm9 ,(XMM9 *8+offes_fltregs)(sp)
+ movq %xmm10,(XMM10*8+offes_fltregs)(sp)
+ movq %xmm11,(XMM11*8+offes_fltregs)(sp)
+ movq %xmm12,(XMM12*8+offes_fltregs)(sp)
+ movq %xmm13,(XMM13*8+offes_fltregs)(sp)
+ movq %xmm14,(XMM14*8+offes_fltregs)(sp)
+ movq %xmm15,(XMM15*8+offes_fltregs)(sp)
+
+ /* calculate sp of method */
+ mov sp,itmp1
+ add $(sizeexecutionstate + REPLACEMENT_ROOM + 8),itmp1
+ mov itmp1,(offes_sp)(sp)
+
+ /* call replace_me */
+ mov -8(itmp1),a0 /* rplpoint * */
+ mov sp,a1 /* arg1: execution state */
+ call replace_me@PLT /* call C function replace_me */
+ call abort@PLT /* NEVER REACHED */
+
+/* asm_replacement_in **********************************************************
+
+ This code writes the given execution state and jumps to the replacement
+ code.
+
+ This function never returns!
+
+ C prototype:
+ void asm_replacement_in(executionstate *es);
+
+*******************************************************************************/
+
+asm_replacement_in:
+ mov a0,%rbp /* executionstate *es */
+
+ /* set new sp */
+ mov (offes_sp)(%rbp),%rsp
+
+ /* store address of new code */
+ push (offes_pc)(%rbp)
+
+ /* copy registers from execution state */
+ movq (XMM0 *8+offes_fltregs)(%rbp),%xmm0
+ movq (XMM1 *8+offes_fltregs)(%rbp),%xmm1
+ movq (XMM2 *8+offes_fltregs)(%rbp),%xmm2
+ movq (XMM3 *8+offes_fltregs)(%rbp),%xmm3
+ movq (XMM4 *8+offes_fltregs)(%rbp),%xmm4
+ movq (XMM5 *8+offes_fltregs)(%rbp),%xmm5
+ movq (XMM6 *8+offes_fltregs)(%rbp),%xmm6
+ movq (XMM7 *8+offes_fltregs)(%rbp),%xmm7
+ movq (XMM8 *8+offes_fltregs)(%rbp),%xmm8
+ movq (XMM9 *8+offes_fltregs)(%rbp),%xmm9
+ movq (XMM10*8+offes_fltregs)(%rbp),%xmm10
+ movq (XMM11*8+offes_fltregs)(%rbp),%xmm11
+ movq (XMM12*8+offes_fltregs)(%rbp),%xmm12
+ movq (XMM13*8+offes_fltregs)(%rbp),%xmm13
+ movq (XMM14*8+offes_fltregs)(%rbp),%xmm14
+ movq (XMM15*8+offes_fltregs)(%rbp),%xmm15
+
+ mov (RAX*8+offes_intregs)(%rbp),%rax
+ mov (RBX*8+offes_intregs)(%rbp),%rbx
+ mov (RCX*8+offes_intregs)(%rbp),%rcx
+ mov (RDX*8+offes_intregs)(%rbp),%rdx
+ mov (RSI*8+offes_intregs)(%rbp),%rsi
+ mov (RDI*8+offes_intregs)(%rbp),%rdi
+ mov (R8 *8+offes_intregs)(%rbp),%r8
+ mov (R9 *8+offes_intregs)(%rbp),%r9
+ mov (R10*8+offes_intregs)(%rbp),%r10
+ mov (R11*8+offes_intregs)(%rbp),%r11
+ mov (R12*8+offes_intregs)(%rbp),%r12
+ mov (R13*8+offes_intregs)(%rbp),%r13
+ mov (R14*8+offes_intregs)(%rbp),%r14
+ mov (R15*8+offes_intregs)(%rbp),%r15
+
+ mov (RBP*8+offes_intregs)(%rbp),%rbp
+
+ /* jump to new code */
+ ret
+
/* asm_builtin_x2x *************************************************************
* *
* Wrapper functions for float to int corner cases *
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/
Changes: Christian Ullrich
Edwin Steiner
- $Id: codegen.c 4615 2006-03-15 16:36:43Z twisti $
+ $Id: codegen.c 4623 2006-03-16 00:05:18Z edwin $
*/
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
+#include "vm/jit/replace.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
builtintable_entry *bte;
methoddesc *md;
+ rplpoint *replacementpoint;
/* prevent compiler warnings */
/* end of header generation */
+ replacementpoint = cd->code->rplpoints;
+
/* walk through all basic blocks */
for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
bptr->mpc);
}
+ /* handle replacement points */
+
+ if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+ replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
+
+ replacementpoint++;
+ }
+
/* copy interface registers to their destination */
src = bptr->instack;
}
}
+ /* generate replacement-out stubs */
+
+ {
+ int i;
+ s4 displacement;
+
+ replacementpoint = cd->code->rplpoints;
+ for (i=0; i<cd->code->rplpointcount; ++i, ++replacementpoint) {
+ /* check code segment size */
+
+ MCODECHECK(512);
+
+ /* note start of stub code */
+
+ replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
+
+ /* make machine code for patching */
+
+ displacement = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
+ replacementpoint->mcode = 0xe9 | ((u8)displacement << 8);
+
+ /* push address of `rplpoint` struct */
+
+ M_MOV_IMM(replacementpoint, REG_ITMP3);
+ M_PUSH(REG_ITMP3);
+
+ /* jump to replacement function */
+
+ M_MOV_IMM(asm_replacement_out, REG_ITMP3);
+ M_JMP(REG_ITMP3);
+ }
+ }
+
codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
/* everything's ok */
Authors: Christian Thalinger
- Changes:
+ Changes: Edwin Steiner
- $Id: md.c 4357 2006-01-22 23:33:38Z twisti $
+ $Id: md.c 4623 2006-03-16 00:05:18Z edwin $
*/
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.h"
+#include "vm/options.h" /* XXX debug */
+#include "vm/jit/disass.h" /* XXX debug */
/* md_init *********************************************************************
}
+/* md_patch_replacement_point **************************************************
+
+ Patch the given replacement point.
+
+*******************************************************************************/
+
+void md_patch_replacement_point(rplpoint *rp)
+{
+ u8 mcode;
+
+ /* XXX this is probably unsafe! */
+
+ /* save the current machine code */
+ mcode = *(u8*)rp->pc;
+
+ /* write spinning instruction */
+ *(u2*)(rp->pc) = 0xebfe;
+
+ /* write 5th byte */
+ rp->pc[4] = (rp->mcode >> 32);
+
+ /* write first word */
+ *(u4*)(rp->pc) = (u4) rp->mcode;
+
+ /* store saved mcode */
+ rp->mcode = mcode;
+
+ {
+ u1* u1ptr = rp->pc;
+ DISASSINSTR(u1ptr);
+ fflush(stdout);
+ }
+
+ /* XXX if required asm_cacheflush(rp->pc,8); */
+}
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/