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