📄 codeseq.c
字号:
/* codeseq.c - module to allow RDI code sequences to be run on ARMulator
* Copyright (c) 2001 ARM Limited. All Rights Reserved.
*
* RCS $Revision: 1.2.2.22.2.1 $
* Checkin $Date: 2002/06/13 20:48:13 $
* Revising $Author: gevans $
*/
#define MODEL_NAME Codeseq
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h> /* for strcpy */
#include "armul_cnf.h"
#include "minperip.h"
#include "armul_callbackid.h"
#include "armul_agent.h"
#include "disass.h"
#ifdef SOCKETS
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include "armul_mem.h"
#include "rdi_sdm.h"
#ifndef NDEBUG
# if 1
# else
# define VERBOSE_SAVEDREGS
# define VERBOSE_BUS
# define VERBOSE_RDI_LOG
# define VERBOSE_SDM
# endif
#endif
#define CURRENTMODE RDIMode_Curr
/* MOV Rd,Rm; Rd in bits 12..15, Rm in bits 0..3 */
#define ARM_NOP_INSTR 0xE1A00000
/* ADDS Rd, Rn, #0; Rd in bits 0..2, Rn in bits 3..5. */
#define THUMB_NOP_INSTR 0x1C00
/* static ARMword nop_instr[5] = {
0,0,THUMB_NOP_INSTR,0,ARM_NOP_INSTR }; */
BEGIN_STATE_DECL(Codeseq)
struct RDICodeSequence_Data CodeSequenceToRun;
ARMword RegsSavedForRunCodeSequence[16];
ARMul_MemInterface bus_mem, child;
ARMul_MemInterfaceRef mem_ref;
ARMword last_address;
unsigned instr_size; /* 4 for ARM, 2 for Thumb */
ARMword base_address;
ARMword stop_pc; /* When to stop! */
bool_int verbose;
bool_int InPreamble;
END_STATE_DECL(Codeseq)
static unsigned CodeseqMemInfo(void *handle, unsigned type, ARMword *pID,
uint64 *data)
{
CodeseqState *mem = (CodeseqState *)handle;
if (mem->child.mem_info)
{
return mem->child.mem_info(mem->child.handle,type,pID,data);
}
else
{
return RDIError_UnimplementedMessage;
}
}
static int Codeseq_MemAccess(void *handle, ARMWord address, ARMWord *data,
unsigned acc);
static int Codeseq_MemAccessSA(void *handle,ARMWord address, ARMWord *data,
unsigned acc);
static void Codeseq_MemAccessHarvard(void *handle,
ARMword daddr,ARMword *ddata, ARMul_acc dacc, int *drv,
ARMword iaddr,ARMword *idata, ARMul_acc iacc, int *irv);
/* Aims to return a value in microseconds */
static ARMTime CodeseqReadClock(void *handle)
{
CodeseqState *mem = (CodeseqState *)handle;
if (mem->child.read_clock)
{
return mem->child.read_clock(mem->child.handle);
}
else
{
return 0L;
}
}
static const ARMul_Cycles *CodeseqReadCycles(void *handle)
{
CodeseqState *mem = (CodeseqState *)handle;
if (mem->child.read_cycles)
{
return mem->child.read_cycles(mem->child.handle);
}
else
{
return NULL;
}
}
static uint32 CodeseqGetCycleLength(void *handle)
{
CodeseqState *mem = (CodeseqState *)handle;
if (mem->child.get_cycle_length)
return mem->child.get_cycle_length(mem->child.handle);
return 0;
}
static void CodeseqCoreException(void *handle,ARMword address,
ARMword penc)
{
CodeseqState *cs = (CodeseqState *)handle;
cs->child.x.arm8.core_exception(cs->child.handle,address,penc);
}
static unsigned int CodeseqDataCacheBusy(void *handle)
{
CodeseqState *cs = (CodeseqState *)handle;
return cs->child.x.strongarm.data_cache_busy(cs->child.handle);
}
static int Codeseq_MemAccess2(void *handle,
ARMword address,
ARMword *data,
ARMul_acc access_type)
{
CodeseqState *state = (CodeseqState *)handle;
if(!(acc_nOPC(access_type)))
{
return Codeseq_MemAccess(handle, address, data, access_type);
}
else
{
int err =
state->child.x.arm8.access2(state->child.handle,
address,data,access_type);
return err;
}
}
/* This is only for ARM7 (and ARM6) cores. */
static int Codeseq_MemAccess(void *handle,
ARMword address,
ARMword *data,
ARMul_acc access_type)
{
CodeseqState *state = (CodeseqState *)handle;
armul_MemAccess *mem_access=state->child.x.basic.access;
RDICodeSequence_Data *cs = &state->CodeSequenceToRun;
UNUSEDARG(address);
UNUSEDARG(data);
UNUSEDARG(access_type);
if (access_type & ACCESS_IDLE)
return PERIP_OK;
if(!(acc_nOPC(access_type)))
{
switch(acc_WIDTH(access_type))
{
case BITS_16:
{
uint16* ip2 = (uint16*)cs->instructions;
unsigned offset = (address - state->base_address)>>1;
if (offset < cs->numInstructions)
{
*data = ip2[offset];
}
else
{
*data = THUMB_NOP_INSTR;
}
return PERIP_OK;
}
default:
# ifndef NDEBUG
Hostif_ConsolePrint(state->hostif,"Codeseq : Unexpected access-size. %u\n", acc_WIDTH(access_type));
/* fallthru */
# endif
case BITS_32:
{
unsigned offset = (address - state->base_address)>>2;
if (!state->InPreamble && offset < cs->numInstructions)
{
*data = cs->instructions[offset];
}
else
{
unsigned Reg = ((offset - cs->numInstructions) & 15);
*data = ARM_NOP_INSTR + Reg + (Reg << 12);
}
#ifdef VERBOSE_SDM
Hostif_ConsolePrint(state->hostif,"SDM A:%08x, I:%08x\n",
(unsigned)address,
(unsigned)*data);
#endif
return PERIP_OK;
}
case BITS_64: /* E.g. ARM8 */
{
int err1 = Codeseq_MemAccess(handle,address,data,
access_type - 1);
int err2 = Codeseq_MemAccess(handle,address+4,data+1,
access_type - 1);
(void)err1; (void)err2;
return PERIP_OK2;
}
}
# ifdef VERBOSE_CODESEQ_END
Hostif_ConsolePrint(state->hostif,"Addr:%08x, LAST:%08x\n",
(unsigned)address,
(unsigned)state->last_address);
# endif
}
/*
* Need to pass data access on to mem system.
* NB data-aborts are bad news here.
*/
return mem_access(state->child.handle,address,data,access_type);
}
static int Codeseq_MemAccessSA(void *handle,
ARMword address,
ARMword *data,
ARMul_acc access_type)
{
CodeseqState *state = (CodeseqState *)handle;
RDICodeSequence_Data *cs = &state->CodeSequenceToRun;
UNUSEDARG(address);
UNUSEDARG(data);
UNUSEDARG(access_type);
if(!(acc_nOPC(access_type)))
{
if (cs->numInstructions > 0)
{
--cs->numInstructions;
if (acc_WIDTH(access_type) == BITS_16)
{
uint16* ip2 = (uint16*)cs->instructions;
ARMWord rv = *(ip2++);
cs->instructions = (uint32*)ip2;
*data = rv;
state->last_address = address;
return PERIP_OK;
}
else
{
uint32 rv = *(cs->instructions++);
*data = rv;
state->last_address = address;
return PERIP_OK;
}
}
return (unsigned)PERIP_DABORT; /* Ouch! */
}
return
state->child.x.strongarm.access(state->child.handle,address,data,access_type);
}
static void Codeseq_MemAccessHarvard(void *handle,
ARMword daddr,ARMword *ddata, ARMul_acc dacc, int *drv,
ARMword iaddr,ARMword *idata, ARMul_acc iacc, int *irv)
{
CodeseqState *state = (CodeseqState *)handle;
ARMWord dummy_idata = 0;
ARMul_acc dummy_iacc = ACCESS_IDLE + ACCESS_INSTR;
int dummy_irv = 0;
/* It is a requirement on the core-models that they clear *irv when
* they want a new opcode. (This test isn't needed while we don't
* generate D-side waits, but it's in here while we remember.)
*/
if (!*irv) /* Only return opcode when requested */
{
if(!(acc_nMREQ(iacc)))
{
*irv = Codeseq_MemAccess(state,iaddr,idata,iacc);
}
else
*irv = PERIP_OK;
}
state->child.x.pipe_arm9.harvard_access(
state->child.handle,
daddr, ddata, dacc, drv,
iaddr, &dummy_idata, dummy_iacc, &dummy_irv);
#ifndef NDEBUG
if (state->verbose)
{
if (*irv!=PERIP_OK) Hostif_ConsolePrint(state->hostif,"Warning, FPE i returns %d\n",*irv);
if (*drv!=PERIP_OK) Hostif_ConsolePrint(state->hostif,"Warning, FPE d returns %d\n",*drv);
}
#endif
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -