Extracting native code from C
Marcus Denker
marcus at ira.uka.de
Thu Mar 14 00:26:55 UTC 2002
On Wed, Mar 13, 2002 at 06:39:39PM -0500, Anthony Hannan wrote:
> John M McIntosh <johnmci at smalltalkconsulting.com> wrote:
> > Normally you need to indicate to the hosting OS and processor that
> > this chunk of data is now instructions.
>
> OK, I give up. I can't find any references on the Internet that talk
> about how to do this, even in assembly language. Any help? It can be
> for any machine.
>
Hi Anthony,
have a look at iflush() in the attached file. This is from ccg,
the runtime assembler that is used by J3.
Marcus
--
Marcus Denker marcus at ira.uka.de -- Squeak! http://squeakland.org
-------------- next part --------------
/* asm-cache.h -- instruction/data cache synchronisation
*
* Copyright (C) 1999, 2000 Ian Piumarta <ian.piumarta at inria.fr>
* Changes Nov 17th, John M McIntosh <johnmci at smalltalkconsulting.com> reworked cache flush logic per input from Linux 2.4
*
* This file is part of CCG.
*
* CCG is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* CCG is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the file COPYING for more details.
*
* Last edited: Thu Jan 13 12:00:45 2000 by piumarta (Ian Piumarta) on pingu
*/
#ifndef __ccg_asm_cache_h
#define __ccg_asm_cache_h
#define FASTERCACHE
int cacheLineSize=0,cacheLineSizeMinusOne=0,cacheLineShift=0;
#if defined(__i386__) /**** i386 ****/
# define iflush(first,last)
#elif defined(__PPC__) || defined(_POWER) || defined(_IBMR2) /**** PowerPC ****/
extern int cacheLineSize,cacheLineSizeMinusOne,cacheLineShift;
void calculateSizeOfCacheLinesAndPower();
# if defined(__GNUC__)
static void iflush(register insn *addr, register insn *last)
{
#ifdef FASTERCACHE
register int rcacheSize,rcacheSizeMinusOne,rcacheShift;
if (last <= addr) return;
if (cacheLineSize == 0) {
calculateSizeOfCacheLinesAndPower();
}
rcacheSize = cacheLineSize;
rcacheShift = cacheLineShift;
rcacheSizeMinusOne = cacheLineSizeMinusOne;
asm volatile ("andc %0,%0,%1": :"r"(addr), "r"(rcacheSizeMinusOne));
asm volatile ("subf %1,%0,%1": :"r"(addr),"r"(last));
asm volatile ("add %0,%0,%2; srw. %0,%0,%1; mtctr %0": : "r"(last), "r"(rcacheShift), "r"(rcacheSizeMinusOne));
asm volatile ("mr 6,%0": : "r"(addr));
asm volatile ("L1: dcbst 0,%0;add %0,%0,%1 ; bdnz L1": : "r"(addr), "r"(rcacheSize));
asm volatile ("sync; mtctr %0": : "r"(last)); /* wait for dcbst's to get to ram */
asm volatile ("L2: icbi 0,6; add 6,6,%0; bdnz L2; sync; isync; ": : "r"(rcacheSize));
#else
while (addr < last) {
asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r"(addr));
++addr; /* conservative */
}
#endif
}
# elif defined(macintosh) || defined(__MWERKS__)
/* PowerMac: assumes CodeWarrior 8 or later (other compilers might barf) */
/* (tho' this probably works with MrC and Motorola compilers too...) */
static asm void iflush(register insn *addr, register insn *last)
{
if (cacheSize == 0) {
calculateSizeOfCacheLinesAndPower();
}
iasmflush(register insn *addr, register insn *last);
}
# pragma internal on
static asm void iasmflush(register insn *addr, register insn *last)
{
register int rcacheSize,rcacheSizeMinusOne,rcacheShift;
#ifdef FASTERCACHE
l rcacheSize,cacheLineSize
l rcacheSizeMinusOne,cacheLineSizeMinusOne
l rcacheShift,cacheLineShift
cmplw cr1, addr, last
bgelr cr1 // return if addr >= last
andc addr,addr,rcacheSizeMinusOne
subf last,addr,last
add last,last,rcacheSizeMinusOne
srw. last,last,rcacheShift
beqlr
mtctr last
mr r6,addr
L1: dcbst 0,addr
add addr,addr,rcacheSize
bdnz L1
sync /* wait for dcbst's to get to ram */
mtctr last
L2: icbi 0,r6
add r6,r6,rcacheSize
bdnz L2
sync
isync
blr
#else
cmplw cr1, addr, last
bgelr cr1 // return if addr >= last
loop: dcbst r0, addr // flush d-cache
sync
icbi r0, addr // sync i-cache
isync
addi addr, addr, 4 // next cache line (4 is very conservative)
cmplw cr1, addr, last // finished?
blt cr1, loop // not yet...
blr // go bye bye
#endif
}
# pragma internal off
# else
# define _ASM_NOCOMP
# endif
#elif defined(__sparc__) /**** Sparc ****/
# if defined(__GNUC__)
static void iflush(register insn *addr, register insn *last)
{
asm volatile ("stbar"); /* PSO memory model */
while (addr < last) {
asm volatile ("flush %0"::"r"(addr)); /* all memory models */
++addr; /* conservative */
}
/* [SPARC Architecture Manual v8, page 139, implementation note #5] */
asm volatile ("nop; nop; nop; nop; nop");
}
# else
# define _ASM_NOCOMP
# endif
#elif 1
# define _ASM_NOARCH
#endif
#ifdef _ASM_NOCOMP
# error: please reimplement iflush() for your compiler,
# error: and EMAIL THE CODE to: ian.piumarta at inria.fr
#endif
#ifdef _ASM_NOARCH
# error: please implement iflush() for your architecture,
# error: and EMAIL THE CODE to: ian.piumarta at inria.fr
#endif
# if defined(__GNUC__)
static void dodcbz(register long *addr)
{
asm volatile ("li 0,0; dcbz %0,0": : "r"(addr));
}
# elif defined(macintosh) || defined(__MWERKS__)
# pragma internal on
static asm void dodcbz(register long *addr)
{
dcbz addr,0
}
# pragma internal off
# endif
void calculateSizeOfCacheLinesAndPower() {
char bufferSpace[8192];
long *bufferLongPtr;
int i,counter=0,power;
bufferLongPtr = (long *) &bufferSpace;
for(i=0;i<2048;i++)
*bufferLongPtr++ = 0xFFFFFFFF;
bufferLongPtr = (long *) &bufferSpace[4096];
dodcbz(bufferLongPtr);
for(i=0;i<8192;i++)
if(bufferSpace[i] == 0x00)
counter++;
cacheLineSize = counter;
cacheLineSizeMinusOne = counter-1;
for(i=1;i<=13;i++) {
power = 1<<i;
if (cacheLineSizeMinusOne < power) {
cacheLineShift = i;
return;
}
}
cacheLineShift = 13;
}
#endif /* __ccg_asm_cache_h */
More information about the Squeak-dev
mailing list
|