Update of /cvsroot/arcem/arcem/riscos-single
In directory vz-cvs-4.sog:/tmp/cvs-serv17456/build/riscos-single

Modified Files:
        Code,ffb ControlPane.c DispKbd.c filecalls.c 
Added Files:
        filecalls_internal.h prof.s realmain.s sound.c soundbuf.s 
Log Message:
Merge arcem-fast to trunk



--- NEW FILE: soundbuf.s ---
@ 
@ riscos-single/soundbuf.s
@ 
@ (c) 2011 Jeffrey Lee <[email protected]>
@ 
@ Basic SharedSound sound driver for ArcEm, based in part on my SharedSound
@ tutorial from http://www.iconbar.com/forums/viewthread.php?threadid=10778
@
@ This code handles filling the SharedSound buffer from the contents of the
@ buffer in ArcEm's RISC OS frontend (riscos-single/sound.c).
@
@ At the moment only basic sample rate conversion is applied - no linear
@ interpolation or anything like that.
@

.set X_Bit, 0x20000
.set XSharedSound_RemoveHandler, 0x04B441 + X_Bit

.text

.global buffer_fill
.global error_handler

routine_params:
        .word sound_buffer      @ R0
        .word sound_buffer_in   @ R3
buffer_out_ptr:
        .word sound_buffer_out  @ R4
        .word sound_rate        @ R5
        .word sound_buff_mask   @ R6
frac_step:
        .word 0 @ R7, current fractional step

sound_handler_id_ptr:
        .word sound_handler_id

buffer_fill:
        @ R0 = our parameter (unused)
        @ R1 = buffer base
        @ R2 = buffer end
        @ R3 = flags (ignored)
        @ R4 = Sample frequency (ignored)
        @ R5 = Sample period (ignored)
        @ R6 = Fractional step (ignored)
        @ R7 = LR volume (ignored)
        @ R8 = Pointer to fill code (ignored)

#if 0
        @ First, check if we need to clear the buffer or add to it
        TST R3,#1
        ORR R3,R3,#1
        STMFD R13!,{R0-R10,R14}
        BNE nozeros
        MOV R9,#0
        MOV R10,R1
zeroloop:
        STR R9,[R10],#4
        CMP R10,R2
        BLT zeroloop
nozeros:
        @ Get our params
        ADR R0,routine_params
        LDMIA R0,{R0,R3-R7}
        LDR R3,[R3]
        LDR R4,[R4]
        LDR R5,[R5]
        LDR R6,[R6]
        @ Loop and fill
        SUBS R3,R3,R4 @ Number of samples available
        BLE endloop @ No more input data
mainloop:
        AND R8,R4,R6 @ Pos to read from
        LDR R10,[R1] @ dest data
        LDR R9,[R0,R8,LSL #1] @ Get input pair
        ADD R10,R10,R9 @ Mix in (no overflow checks!)
        STR R10,[R1],#4
        ADD R7,R7,R5 @ Increment fraction accumulator
        MOV R10,R7,LSR #24 @ Get any whole movements
        BIC R7,R7,#0xFF000000 @ Get rid of whole part
        ADD R4,R4,R10,LSL #1 @ Increment out pos
        @ Check for buffer ends
        SUBS R3,R3,R10,LSL #1
        BLE endloop
        CMP R1,R2
        BLT mainloop
endloop:
        @ Store back updated values
        LDR R3,buffer_out_ptr
        STR R7,frac_step
        STR R4,[R3]
        LDMFD R13!,{R0-R10,PC}
#else
        @ New version for the new sound mixer
        @ sound_rate just acts as a pause flag, since the data should be at the 
correct rate already
        TST R3,#1
        ORR R3,R3,#1
        STMFD R13!,{R0-R8,R14}
        MOVEQ R14,#0 @ R14 becomes mix flag
        @ Get our params
        ADR R0,routine_params
        LDMIA R0,{R0,R3-R6}
        LDR R3,[R3]
        LDR R4,[R4]
        LDR R5,[R5]
        LDR R6,[R6]
        CMP R3,#0
        BEQ nodata
        SUBS R3,R3,R4 @ Number of samples available
        BLE nodata @ No more input data
        CMP R14,#0
        BEQ copyloop
mixloop:
        AND R8,R4,R6 @ Pos to read from
        LDR R14,[R1] @ dest data
        ADD R4,R4,#4 @ Increment out pos
        LDR R7,[R0,R8,LSL #1] @ Get input pair
        SUBS R3,R3,#2
        ADD R14,R14,R7 @ Mix in (no overflow checks!)
        STR R14,[R1],#2
        @ Check for buffer ends
        BLE mix_done
        CMP R1,R2
        BLT mixloop
mix_done:
        @ Store back updated values
        LDR R3,buffer_out_ptr
        STR R4,[R3]
        LDMFD R13!,{R0-R8,PC}

copyloop:
        AND R8,R4,R6 @ Pos to read from
        LDR R9,[R0,R8,LSL #1] @ Get input pair
        ADD R4,R4,#2 @ Increment out pos
        STR R9,[R1],#4
        @ Check for buffer ends
        SUBS R3,R3,#2
        BLE zeroloop
        CMP R1,R2
        BLT copyloop
        @ Store back updated values
        LDR R3,buffer_out_ptr
        STR R4,[R3]
        LDMFD R13!,{R0-R8,PC}

nodata:
        CMP R14,#0
        LDMNEFD R13!,{R0-R8,PC} @ No source data, and mixing in, therefore no 
work to do
        @ Else must fill buffer with zeros
        MOV R3,#0 @ Note: Alternate entry points should have R3 as zero already
zeroloop:
        CMP R1,R2
        STRLT R3,[R1],#4
        BLT zeroloop
        @ Store back updated values
        LDR R3,buffer_out_ptr
        STR R4,[R3]
        LDMFD R13!,{R0-R8,PC}
#endif

error_handler:
        STMFD R13!,{R0-R2,R14}
        MRS R2,CPSR
        @ Check if sound handler installed, remove
        LDR R1,sound_handler_id_ptr
        LDR R0,[R1]
        CMP R0,#0
        SWINE XSharedSound_RemoveHandler
        MOV R0,#0
        STR R0,[R1]
        MSR CPSR_f,R2
        LDMFD R13!,{R0-R2,PC}

Index: filecalls.c
===================================================================
RCS file: /cvsroot/arcem/arcem/riscos-single/filecalls.c,v
retrieving revision 1.1
retrieving revision 1.3
diff -u -d -r1.1 -r1.3
--- filecalls.c 25 Feb 2006 00:02:31 -0000      1.1
+++ filecalls.c 12 May 2012 17:34:51 -0000      1.3
@@ -0,0 +1,117 @@
+/* filecalls.c posix implimentatation of the abstracted interface to accesing 
host
+   OS file and Directory functions.
+   Copyright (c) 2005 Peter Howkins, covered under the GNU GPL see file 
COPYING for more
+   details */
+/* ansi includes */
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+/* posix includes */
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+/* application includes */
+#include "filecalls.h"
+
+/**
+ * Directory_Open
+ *
+ * Open a directory so that it's contents can be scanned
+ *
+ * @param sPath Location of directory to scan
+ * @param hDir Pointer to a Directory struct to fill in
+ * @returns true on success false on failure
+ */
+bool Directory_Open(const char *sPath, Directory *hDirectory)
+{
+  assert(sPath);
+  assert(*sPath);
+  assert(hDirectory);
+
+  hDirectory->hDir = opendir(sPath);
+
+  if(NULL == hDirectory->hDir) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+/**
+ * Directory_Close
+ *
+ * Close a previously opened Directory
+ *
+ * @param hDirectory Directory to close
+ */
+void Directory_Close(Directory hDirectory)
+{
+  closedir(hDirectory.hDir);
+}
+
+/**
+ * Directory_GetNextEntry
+ *
+ * Get the next entry in a directory
+ *
+ * @param hDirectory pointer to Directory to get entry from
+ * @returns String of filename or NULL on EndOfDirectory
+ */
+char *Directory_GetNextEntry(Directory *hDirectory)
+{
+  struct dirent *phDirEntry;
+  
+  assert(hDirectory);
+  
+  phDirEntry = readdir(hDirectory->hDir);
+  if(phDirEntry) {
+    return phDirEntry->d_name;
+  } else {
+    return NULL;
+  }
+}
+
+/**
+ * File_GetInfo
+ *
+ * Fills in lots of useful info about the passed in file
+ *
+ * @param sPath Path to file to check
+ * @param phFileInfo pointer to FileInfo struct to fill in
+ * @returns false on failure true on success
+ */
+bool File_GetInfo(const char *sPath, FileInfo *phFileInfo)
+{
+  struct stat hEntryInfo;
+
+  assert(sPath);
+  assert(phFileInfo);
+
+  if (stat(sPath, &hEntryInfo) != 0) {
+    fprintf(stderr, "Warning: could not stat() entry \'%s\': %s\n",
+            sPath, strerror(errno));
+    return false;
+  }
+  
+  /* Initialise components */
+  phFileInfo->bIsRegularFile = false;
+  phFileInfo->bIsDirectory   = false;
+
+  if (S_ISREG(hEntryInfo.st_mode)) {
+    phFileInfo->bIsRegularFile = true;
+  }
+
+  if (S_ISDIR(hEntryInfo.st_mode)) {
+    phFileInfo->bIsDirectory = true;
+  }
+  
+  /* Fill in Size */
+  phFileInfo->ulFilesize = hEntryInfo.st_size;
+  
+  /* Success! */
+  return true;
+}
+

Index: Code,ffb
===================================================================
RCS file: /cvsroot/arcem/arcem/riscos-single/Code,ffb,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -d -r1.1.1.1 -r1.3
Binary files /tmp/cvsa8aEhH and /tmp/cvsinMeHc differ

--- NEW FILE: sound.c ---
/*
  riscos-single/sound.c

  (c) 2011 Jeffrey Lee <[email protected]>

  Basic SharedSound sound driver for ArcEm, based in part on my SharedSound
  tutorial from http://www.iconbar.com/forums/viewthread.php?threadid=10778

*/

#include <stdio.h>
#include <stdlib.h>

#include <sys/soundcard.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <pthread.h>
#include <time.h>

#include "../armdefs.h"
#include "../arch/sound.h"
#include "../arch/archio.h"
#include "../arch/displaydev.h"

#include "kernel.h"
#include "swis.h"

/* SharedSound SWI numbers */
#define SharedSound_InstallHandler      0x4B440
#define SharedSound_SampleRate          0x4B446
#define SharedSound_RemoveHandler       0x4B441

int sound_handler_id=0; /* ID of our sound handler (0 if uninstalled) */

#define BUFFER_SAMPLES (32768) /* 16K stereo pairs */

SoundData sound_buffer[BUFFER_SAMPLES];
volatile int sound_buffer_in=BUFFER_SAMPLES; /* Number of samples we've placed 
in the buffer */
volatile int sound_buffer_out=0; /* Number of samples read out by the IRQ 
routine */
int sound_buff_mask=BUFFER_SAMPLES-1; /* For benefit of assembler code */
int sound_rate = 1<<24; /* Fixed output rate! */
static int buffer_threshold; /* Threshold value used to control desired buffer 
level; chosen based around the output sample rate & buffer_seconds */
static float buffer_seconds = 0.2f; /* How much audio we want to try and keep 
buffered */ 

extern void buffer_fill(void); /* Assembler function for performing the buffer 
fills */
extern void error_handler(void); /* Assembler function attached to ErrorV */

static void shutdown_sharedsound(void);

extern void __write_backtrace(int signo);
static void sigfunc(int sig)
{
        shutdown_sharedsound();
#if 0
        /* Dump some emulator state */
        ARMul_State *state = &statestr;
        fprintf(stderr, "r0 = %08x  r4 = %08x  r8  = %08x  r12 = %08x\n"
                        "r1 = %08x  r5 = %08x  r9  = %08x  sp  = %08x\n"
                        "r2 = %08x  r6 = %08x  r10 = %08x  lr  = %08x\n"
                        "r3 = %08x  r7 = %08x  r11 = %08x  pc  = %08x\n"
                      "\n",
          state->Reg[0], state->Reg[4], state->Reg[8], state->Reg[12],
          state->Reg[1], state->Reg[5], state->Reg[9], state->Reg[13],
          state->Reg[2], state->Reg[6], state->Reg[10], state->Reg[14],
          state->Reg[3], state->Reg[7], state->Reg[11], state->Reg[15]);
        int i;
        for(i=0;i<4;i++)
          fprintf(stderr,"Timer%d Count %08x Latch 
%08x\n",i,ioc.TimerCount[i],ioc.TimerInputLatch[i]);
        FILE *f = fopen("$.dump","wb");
        if(f)
        {
                for(i=0;i<1024*1024;i+=4)
                {
                        ARMword word = ARMul_LoadWordS(state,i);
                        if(state->abortSig)
                                break;
                        fwrite(&word,4,1,f);
                }
                fclose(f);
        }
#endif

        /* Now dump a backtrace of ourself */
        __write_backtrace(sig);
        exit(0);
}

static int init_sharedsound(void)
{
        /* Try to register sharedsound handler, return nonzero on failure */
        _kernel_swi_regs regs;
        _kernel_oserror *err;
        /* First load SharedSound if it isn't already loaded
           A *command is the easiest way to do this (usually in your programs 
!Run file, but this demo doesn't have one) */
        system("RMEnsure SharedSound 0.00 IfThere System:Modules.SSound Then 
RMLoad System:Modules.SSound");
        /* Now check whether it is loaded, so we can print a more friendly 
error message than 'SWI xxx not found' */
        regs.r[0] = 18;
        regs.r[1] = (int) "SharedSound";
        if ((err = _kernel_swi(OS_Module,&regs,&regs)))
        {
                fprintf(stderr,"Warning: SharedSound module not loaded, and not 
in System:Modules!\n");
                return 0;
        }
        /* Now we can register our handler */
        regs.r[0] = (int) buffer_fill;
        regs.r[1] = 0;
        regs.r[2] = 1;
        regs.r[3] = (int) "ArcEm";
        regs.r[4] = 0;
        if ((err = _kernel_swi(SharedSound_InstallHandler,&regs,&regs)))
        {
                fprintf(stderr,"Warning: SharedSound_InstallHandler returned 
error %d, %s\n",err->errnum,err->errmess);
                return 0;
        }
        sound_handler_id = regs.r[0];
        /* Install error handlers so we don't crash on exit */
        atexit(shutdown_sharedsound);
#ifdef __TARGET_UNIXLIB__
        /* With UnixLib we need to use signal handlers to catch any errors.
           UnixLib doesn't make it very easy to get user code to run when
           something bad happens :( */
        signal(SIGHUP,sigfunc);
        signal(SIGINT,sigfunc);
        signal(SIGQUIT,sigfunc);
        signal(SIGILL,sigfunc);
        signal(SIGABRT,sigfunc);
        signal(SIGTRAP,sigfunc);
        signal(SIGEMT,sigfunc);
        signal(SIGFPE,sigfunc);
        signal(SIGKILL,sigfunc);
        signal(SIGBUS,sigfunc);
        signal(SIGSEGV,sigfunc);
        signal(SIGSYS,sigfunc);
        signal(SIGPIPE,sigfunc);
        signal(SIGALRM,sigfunc);
        signal(SIGTERM,sigfunc);
        signal(SIGSTOP,sigfunc);
        signal(SIGTSTP,sigfunc);
        signal(SIGTTIN,sigfunc);
        signal(SIGTTOU,sigfunc);
        signal(SIGOSERROR,sigfunc);
#else
        /* With SCL a simple error handler seems to do the trick */
        regs.r[0] = 1;
        regs.r[1] = (int) error_handler;
        regs.r[2] = 0;
        _kernel_swi(OS_Claim,&regs,&regs);
#endif
        /* Get our sample rate */
        
_swix(SharedSound_SampleRate,_INR(0,1)|_OUT(1),sound_handler_id,0,&Sound_HostRate);
        /* Calculate the buffer threshold value
           This is the low threshold value, so we divide by 512 to get the 
desired level, then by two again to get the low level */
        buffer_threshold = ((int)(buffer_seconds*((float)Sound_HostRate)))>>10;
        /* Low thresholds may cause issues */
        if(buffer_threshold<Sound_BatchSize*4)
                buffer_threshold = Sound_BatchSize*4;
        /* Big thresholds will cause problems too! */
        if(buffer_threshold*4 > BUFFER_SAMPLES)
                buffer_threshold = BUFFER_SAMPLES>>2;
        fprintf(stderr,"Host audio rate %dHz, using buffer threshold 
%d\n",Sound_HostRate>>10,buffer_threshold);
        return 0;
}                           

static void shutdown_sharedsound(void)
{
        _kernel_swi_regs regs;
        /* Deregister sharedsound handler */
        if(sound_handler_id)
        {
                regs.r[0] = sound_handler_id;
                _kernel_swi(SharedSound_RemoveHandler,&regs,&regs);
                sound_handler_id = 0;
        }
        /* Remove error handler */
        regs.r[0] = 1;
        regs.r[1] = (int) error_handler;
        regs.r[2] = 0;
        _kernel_swi(OS_Release,&regs,&regs); 
}

int Sound_InitHost(ARMul_State *state)
{
  /* We want the right channel first */
  eSound_StereoSense = Stereo_RightLeft;

  /* Use a decent batch size */
  Sound_BatchSize = 256;

  /* Default 20833Hz sample rate if no SharedSound? */
  Sound_HostRate = (1000000<<10)/48;

#ifndef PROFILE_ENABLED
  if (init_sharedsound())
  {
    fprintf(stderr,"Error: Couldn't register sound handler\n");
    return -1;
  }
#endif

  return 0;
}

SoundData *Sound_GetHostBuffer(int32_t *destavail)
{
  /* Work out how much space is available until next wrap point, or we start 
overwriting data */
  if(!sound_handler_id)
  {
    *destavail = BUFFER_SAMPLES>>1;
    return sound_buffer;
  }
  int used = sound_buffer_in-sound_buffer_out;
  int ofs = sound_buffer_in & sound_buff_mask;
  int buffree = BUFFER_SAMPLES-MAX(ofs,used);
  *destavail = buffree>>1;
  return sound_buffer + ofs;
}

void Sound_HostBuffered(SoundData *buffer,int32_t numSamples)
{
  if(!sound_handler_id)
    return;

  int used = sound_buffer_in-sound_buffer_out;
  int buffree = BUFFER_SAMPLES-used;

  numSamples <<= 1;

  sound_buffer_in += numSamples;

  if(buffree == numSamples)
  {
    fprintf(stderr,"*** sound overflow! ***\n");
    if(Sound_FudgeRate < -10)
      Sound_FudgeRate = Sound_FudgeRate/2;
    else
      Sound_FudgeRate+=10;
  }
  else if(!used)
  {
    fprintf(stderr,"*** sound underflow! ***\n");
    if(Sound_FudgeRate > 10)
      Sound_FudgeRate = Sound_FudgeRate/2;
    else
      Sound_FudgeRate-=10;
  }
  else if(used < buffer_threshold)
  {
    Sound_FudgeRate-=3;
  }
  else if(used < buffer_threshold*3)
  {
    Sound_FudgeRate+=3;
  }
  else if(Sound_FudgeRate)
  {
    /* Bring the fudge value back towards 0 until we go out of the comfort zone 
*/
    Sound_FudgeRate += (Sound_FudgeRate>0?-1:1);
  }
}

--- NEW FILE: realmain.s ---
@
@ riscos-single/realmain.s
@
@ (c) 2011 Jeffrey Lee <[email protected]>
@
@ Part of Arcem released under the GNU GPL, see file COPYING
@ for details.
@
@ Simple wrapper for main() that creates one large stack frame for us to use.
@ This allows us to skip performing stack extension checks in the main code.
@

@ 256K should be far more than enough
#define STACK_SIZE (256*1024)

.text

.global main

main:
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     ip, sp, #STACK_SIZE
        bl      __rt_stkovf_split_big
        bl      fakemain
        ldmea   fp, {fp, sp, pc}


--- NEW FILE: filecalls_internal.h ---
/* filecalls_internal.h
   Copyright (c) 2005 Peter Howkins, covered under the GNU GPL see file COPYING 
for more
   details */

#ifndef __FILECALLS_INTERNAL_H
#define __FILECALLS_INTERNAL_H

#include <sys/types.h>
#include <dirent.h>

struct Directory_s {
  DIR *hDir;
};

#define ARCEM_PATH_MAX PATH_MAX

#endif /* __FILECALLS_H */

Index: DispKbd.c
===================================================================
RCS file: /cvsroot/arcem/arcem/riscos-single/DispKbd.c,v
retrieving revision 1.9
retrieving revision 1.11
diff -u -d -r1.9 -r1.11
--- DispKbd.c   10 Mar 2006 18:27:56 -0000      1.9
+++ DispKbd.c   12 May 2012 17:34:51 -0000      1.11
@@ -1,20 +1,12 @@
-/* (c) David Alan Gilbert 1995-1999 - see Readme file for copying info */
+/* (c) David Alan Gilbert 1995-1999 - see Readme file for copying info
+   Hacked about with for new display driver interface by Jeffrey Lee, 2011 */
 /* Display and keyboard interface for the Arc emulator */
 
-// #define MOUSEKEY XK_KP_Add
-
-#define KEYREENABLEDELAY 1000
-
-/*#define DEBUG_VIDCREGS*/
-/* NOTE: Can't use ARMul's refresh function because it has a small
[...1739 lines suppressed...]
+  if(hArcemConfig.eDisplayDriver == DisplayDriver_Standard)
+    DisplayDev_UseUpdateFlags = 1;
+  /* Rebuild fastmap for DisplayDev_UseUpdateFlags changes */
+  ARMul_RebuildFastMap();
+  /* Gobble any keyboard input */
+  while(_swi (ArcEmKey_GetKey, _RETURN(0))) {};
+  /* Reset EmuRate */
+  EmuRate_Reset(&statestr);
+#ifdef PROFILE_ENABLED
+  if(enable_profile)
+  {
+    /* Start profiling */
+    Prof_Reset();
+  }
+  Prof_BeginFunc(Keyboard_Poll);
 #endif
 }
-
-
+#endif

Index: ControlPane.c
===================================================================
RCS file: /cvsroot/arcem/arcem/riscos-single/ControlPane.c,v
retrieving revision 1.3
retrieving revision 1.5
diff -u -d -r1.3 -r1.5
--- ControlPane.c       9 May 2003 10:54:56 -0000       1.3
+++ ControlPane.c       12 May 2012 17:34:51 -0000      1.5
@@ -5,7 +5,6 @@
 #include "../armdefs.h"
 #include "archio.h"
 #include "armarc.h"
-#include "DispKbd.h"
 #include "ControlPane.h"
 
 void ControlPane_Init(ARMul_State *state)

--- NEW FILE: prof.s ---
@
@ prof.s
@
@ (c) 2011 Jeffrey Lee <[email protected]>
@
@ Part of Arcem released under the GNU GPL, see file COPYING
@ for details.
@
@ Very nasty CPU profiling code for RISC OS hosts running on Iyonix or
@ Cortex-A8 machines. This code relies upon the following:
@
@ * Function name poking (-mpoke-function-names) being enabled
@ * 'cortex' #define being set correctly for whether IOP321 or Cortex-A8 code
@   should be used
@ * On IOP321, HAL timer 1 must be free. This also means the results will be in
@   200MHz clock ticks instead of CPU cycles.
@ * On Cortex-A8, the cycle count performance counter must be free
@ * C heap allocations must come from application space, not a dynamic area (a
@   simple malloc is used to estimate how large the program is by looking at the
@   allocation address). This requirement is currently enforced by
@   riscos-single/DispKbd.c
@

.text

prof_buffer_ptr:
.word   0
prof_buffer_size:
.word   0
prof_buffer_offset:
.word   0
prof_fmt_str:
.ascii  "%s,%u,%u\012\000"
.align  2

#define OS_EnterOS 0x16
#define OS_LeaveOS 0x7c
#define OS_Hardware 0x7a

//#define cortex

#ifdef cortex
#define read_timer(out) mrc     p15, 0, out, c9, c13, 0 @ counts up
#else
#define read_timer(out) mrc     p6, 0, out, c3, c1, 0 @ counts down!
#endif

.global Prof_Init
.global Prof_BeginFunc
.global Prof_Begin
.global Prof_EndFunc
.global Prof_End
.global Prof_Dump
.global Prof_Reset

Prof_Init:
        mov     ip, sp
        stmfd   sp!, {v5-v6, fp, ip, lr, pc}
        sub     fp, ip, #4
        mov     a1, #4
        bl      malloc
        sub     v5, a1, #0x8000
        str     v5, prof_buffer_size
        bl      free
        mov     a1, v5
        bl      malloc
        str     a1, prof_buffer_ptr
        sub     a2, a1, #0x8000
        str     a2, prof_buffer_offset
        mov     a2, #0
        mov     a3, v5
        bl      memset
#ifdef cortex
        @ configure cycle count performance counter
        swi     OS_EnterOS
        mov     a1, #1
        mcr     p15, 0, a1, c9, c14, 0 @ enable user access to perf counters
        mvn     a1, #0
        mcr     p15, 0, a1, c9, c12, 2 @ disable counters
        mcr     p15, 0, a1, c9, c14, 2 @ disable interrupts
        mov     a1, #0x80000000
        mcr     p15, 0, a1, c9, c12, 1 @ enable cycle count
        mov     a1, #7
        mcr     p15, 0, a1, c9, c12, 0 @ enable & reset
        swi     OS_LeaveOS
#else
        @ No user-mode access to performance counters on XScale, so user timer
        @ 1 instead
        @ Configure it via HAL calls for simplicity
        mov     v5, #0
        mov     a1, #1
        mov     v6, #13
        swi     OS_Hardware @ get IRQ
        mov     v6, #2
        swi     OS_Hardware @ disable IRQ
        mov     a1, #1
        mvn     a2, #0
        mov     v6, #16
        swi     OS_Hardware @ set period to max, enables timer
#endif
        ldmea   fp, {v5-v6, fp, sp, pc}

Prof_Reset:
        ldr     a1, prof_buffer_ptr
        mov     a2, #0
        ldr     a3, prof_buffer_size
        b       memset

Prof_BeginFunc:
        @ a1 = name-poked func ptr
        ldrb    a2, [a1, #-4]!
        sub     a1, a1, a2
Prof_Begin:
        @ a1 = word-aligned const string ptr, must be >= 8 bytes!
        ldr     a3, prof_buffer_offset
        read_timer(a2)
        ldr     a4, [a1, a3]!
#ifdef cortex
        sub     a4, a4, a2 @ sub start time, add finish time
#else
        add     a4, a4, a2 @ add start countdown, sub finish countdown
#endif
        str     a4, [a1]
        mov     pc, lr

Prof_EndFunc:
        @ a1 = name-poked func ptr
        ldrb    a2, [a1, #-4]!
        sub     a1, a1, a2
Prof_End:
        @ a1 = word-aligned const string ptr, must be >= 8 bytes!
        ldr     a3, prof_buffer_offset
        read_timer(a2)
        add     a1, a1, a3
        ldmia   a1, {a3,a4}
#ifdef cortex
        add     a3, a3, a2
#else
        sub     a3, a3, a2
#endif
        add     a4, a4, #1
        stmia   a1, {a3,a4}
        mov     pc, lr

Prof_Dump:
        mov     ip, sp
        stmfd   sp!, {a1,v1-v3,fp,ip,lr,pc}
        sub     fp, ip, #4
        sub     sp, sp, #4
        ldr     v1, prof_buffer_ptr
        ldr     v2, prof_buffer_size
        ldr     v3, prof_buffer_offset
        add     v2, v1, v2
        add     v3, v3, #8
.loop:
        ldr     a4, [v1], #4
        cmp     a4, #0
        beq     .skip
        ldr     ip, [v1], #4
        str     ip, [sp]
        sub     a3, v1, v3
        adr     a2, prof_fmt_str
        ldr     a1, [sp, #4]
        bl      fprintf
.skip:
        cmp     v1, v2
        blo     .loop
        ldmea   fp, {v1-v3,fp,sp,pc}


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
-- 
arcem-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/arcem-cvs

Reply via email to