citra-emu
/
citra-canary
Archived
1
0
Fork 0

added various arm modules from skyeye to make project link OK

This commit is contained in:
bunnei 2014-03-29 21:53:07 -04:00
parent 20807c4d5a
commit 6b255111d5
9 changed files with 2582 additions and 166 deletions

View File

@ -139,9 +139,14 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="src\arm\armemu.cpp" /> <ClCompile Include="src\arm\armemu.cpp" />
<ClCompile Include="src\arm\arminit.cpp" /> <ClCompile Include="src\arm\arminit.cpp" />
<ClCompile Include="src\arm\armmmu.cpp" />
<ClCompile Include="src\arm\armos.cpp" />
<ClCompile Include="src\arm\armsupp.cpp" />
<ClCompile Include="src\arm\armvirt.cpp" />
<ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />
<ClCompile Include="src\core.cpp" /> <ClCompile Include="src\core.cpp" />
<ClCompile Include="src\core_timing.cpp" /> <ClCompile Include="src\core_timing.cpp" />
<ClCompile Include="src\elf\elf_reader.cpp" />
<ClCompile Include="src\file_sys\directory_file_system.cpp" /> <ClCompile Include="src\file_sys\directory_file_system.cpp" />
<ClCompile Include="src\file_sys\meta_file_system.cpp" /> <ClCompile Include="src\file_sys\meta_file_system.cpp" />
<ClCompile Include="src\loader.cpp" /> <ClCompile Include="src\loader.cpp" />
@ -165,7 +170,8 @@
<ClInclude Include="src\arm\skyeye_defs.h" /> <ClInclude Include="src\arm\skyeye_defs.h" />
<ClInclude Include="src\core.h" /> <ClInclude Include="src\core.h" />
<ClInclude Include="src\core_timing.h" /> <ClInclude Include="src\core_timing.h" />
<ClInclude Include="src\elf\elf.h" /> <ClInclude Include="src\elf\elf_reader.h" />
<ClInclude Include="src\elf\elf_types.h" />
<ClInclude Include="src\file_sys\directory_file_system.h" /> <ClInclude Include="src\file_sys\directory_file_system.h" />
<ClInclude Include="src\file_sys\file_sys.h" /> <ClInclude Include="src\file_sys\file_sys.h" />
<ClInclude Include="src\file_sys\meta_file_system.h" /> <ClInclude Include="src\file_sys\meta_file_system.h" />

View File

@ -22,6 +22,21 @@
</ClCompile> </ClCompile>
<ClCompile Include="src\system.cpp" /> <ClCompile Include="src\system.cpp" />
<ClCompile Include="src\core_timing.cpp" /> <ClCompile Include="src\core_timing.cpp" />
<ClCompile Include="src\elf\elf_reader.cpp">
<Filter>elf</Filter>
</ClCompile>
<ClCompile Include="src\arm\armsupp.cpp">
<Filter>arm</Filter>
</ClCompile>
<ClCompile Include="src\arm\armvirt.cpp">
<Filter>arm</Filter>
</ClCompile>
<ClCompile Include="src\arm\armmmu.cpp">
<Filter>arm</Filter>
</ClCompile>
<ClCompile Include="src\arm\armos.cpp">
<Filter>arm</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="arm"> <Filter Include="arm">
@ -94,7 +109,10 @@
</ClInclude> </ClInclude>
<ClInclude Include="src\system.h" /> <ClInclude Include="src\system.h" />
<ClInclude Include="src\core_timing.h" /> <ClInclude Include="src\core_timing.h" />
<ClInclude Include="src\elf\elf.h"> <ClInclude Include="src\elf\elf_reader.h">
<Filter>elf</Filter>
</ClInclude>
<ClInclude Include="src\elf\elf_types.h">
<Filter>elf</Filter> <Filter>elf</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>

View File

@ -21,6 +21,19 @@
#include "armemu.h" #include "armemu.h"
#include "armos.h" #include "armos.h"
void
XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword _far)
{
_dbg_assert_msg_(ARM11, false, "ImplementMe: XScale_set_fsr_far!");
//if (!state->is_XScale || (read_cp14_reg(10) & (1UL << 31)) == 0)
// return;
//
//write_cp15_reg(state, 5, 0, 0, fsr);
//write_cp15_reg(state, 6, 0, 0, _far);
}
#define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei
//#include "skyeye_callback.h" //#include "skyeye_callback.h"
//#include "skyeye_bus.h" //#include "skyeye_bus.h"
//#include "sim_control.h" //#include "sim_control.h"
@ -2174,10 +2187,10 @@ ARMul_Emulate26 (ARMul_State * state)
(state, (state,
ARMul_CP15_R5_MMU_EXCPT, ARMul_CP15_R5_MMU_EXCPT,
pc); pc);
if (!XScale_debug_moe //if (!XScale_debug_moe
(state, // (state,
ARMul_CP14_R10_MOE_BT)) // ARMul_CP14_R10_MOE_BT))
break; // break; // Disabled /bunnei
} }
/* Force the next instruction to be refetched. */ /* Force the next instruction to be refetched. */

View File

@ -73,6 +73,7 @@ extern ARMword isize;
#define ASSIGNT(res) state->TFlag = res #define ASSIGNT(res) state->TFlag = res
#define INSN_SIZE (TFLAG ? 2 : 4) #define INSN_SIZE (TFLAG ? 2 : 4)
#else #else
#define TBIT (1L << 5)
#define INSN_SIZE 4 #define INSN_SIZE 4
#define TFLAG 0 #define TFLAG 0
#endif #endif
@ -229,12 +230,12 @@ extern ARMword isize;
} \ } \
while (0) while (0)
#ifndef MODE32 //#ifndef MODE32
#define VECTORS 0x20 #define VECTORS 0x20
#define LEGALADDR 0x03ffffff #define LEGALADDR 0x03ffffff
#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) #define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
#endif //#endif
#define INTERNALABORT(address) \ #define INTERNALABORT(address) \
do \ do \
@ -409,10 +410,12 @@ extern ARMword isize;
|| (! (STATE)->is_XScale) \ || (! (STATE)->is_XScale) \
|| (read_cp15_reg (15, 0, 1) & (1 << (CP)))) || (read_cp15_reg (15, 0, 1) & (1 << (CP))))
*/ */
#define CP_ACCESS_ALLOWED(STATE, CP) \ //#define CP_ACCESS_ALLOWED(STATE, CP) \
( ((CP) >= 14) \ // (((CP) >= 14) \
|| (! (STATE)->is_XScale) \ // || (!(STATE)->is_XScale) \
|| (xscale_cp15_cp_access_allowed(STATE,15,CP))) // || (xscale_cp15_cp_access_allowed(STATE, 15, CP)))
#define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei
/* Macro to rotate n right by b bits. */ /* Macro to rotate n right by b bits. */
#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))

View File

@ -271,7 +271,7 @@ below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function
/* Only initialse the coprocessor support once we /* Only initialse the coprocessor support once we
know what kind of chip we are dealing with. */ know what kind of chip we are dealing with. */
ARMul_CoProInit (state); //ARMul_CoProInit (state); Commented out /bunnei
} }
@ -318,7 +318,7 @@ ARMul_Reset (ARMul_State * state)
state->NumFcycles = 0; state->NumFcycles = 0;
//fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); //fprintf(stderr,"armul_reset 3: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
mmu_reset (state); //mmu_reset (state); Commented out /bunnei
//fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode); //fprintf(stderr,"armul_reset 4: state-> Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);
//mem_reset (state); /* move to memory/ram.c */ //mem_reset (state); /* move to memory/ram.c */
@ -436,7 +436,8 @@ ARMul_DoProg (ARMul_State * state)
} }
else { else {
pc = ARMul_Emulate26 (state); //pc = ARMul_Emulate26 (state); Commented out /bunnei
ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!");
} }
//chy 2006-02-22, should test debugmode first //chy 2006-02-22, should test debugmode first
//chy 2006-04-14, put below codes in ARMul_Emulate //chy 2006-04-14, put below codes in ARMul_Emulate
@ -489,8 +490,10 @@ ARMul_DoInstr (ARMul_State * state)
#endif #endif
} }
else else {
pc = ARMul_Emulate26 (state); //pc = ARMul_Emulate26 (state); Commented out /bunnei
ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!");
}
return (pc); return (pc);
} }
@ -501,78 +504,78 @@ ARMul_DoInstr (ARMul_State * state)
* appropriate vector's memory address (0,4,8 ....) * * appropriate vector's memory address (0,4,8 ....) *
\***************************************************************************/ \***************************************************************************/
//void void
//ARMul_Abort (ARMul_State * state, ARMword vector) ARMul_Abort (ARMul_State * state, ARMword vector)
//{ {
// ARMword temp; ARMword temp;
// int isize = INSN_SIZE; int isize = INSN_SIZE;
// int esize = (TFLAG ? 0 : 4); int esize = (TFLAG ? 0 : 4);
// int e2size = (TFLAG ? -4 : 0); int e2size = (TFLAG ? -4 : 0);
//
// state->Aborted = FALSE; state->Aborted = FALSE;
//
// if (state->prog32Sig) if (state->prog32Sig)
// if (ARMul_MODE26BIT) if (ARMul_MODE26BIT)
// temp = R15PC; temp = R15PC;
// else else
// temp = state->Reg[15]; temp = state->Reg[15];
// else else
// temp = R15PC | ECC | ER15INT | EMODE; temp = R15PC | ECC | ER15INT | EMODE;
//
// switch (vector) { switch (vector) {
// case ARMul_ResetV: /* RESET */ case ARMul_ResetV: /* RESET */
// SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE,
// 0); 0);
// break; break;
// case ARMul_UndefinedInstrV: /* Undefined Instruction */ case ARMul_UndefinedInstrV: /* Undefined Instruction */
// SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE,
// isize); isize);
// break; break;
// case ARMul_SWIV: /* Software Interrupt */ case ARMul_SWIV: /* Software Interrupt */
// SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE,
// isize); isize);
// break; break;
// case ARMul_PrefetchAbortV: /* Prefetch Abort */ case ARMul_PrefetchAbortV: /* Prefetch Abort */
// state->AbortAddr = 1; state->AbortAddr = 1;
// SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
// esize); esize);
// break; break;
// case ARMul_DataAbortV: /* Data Abort */ case ARMul_DataAbortV: /* Data Abort */
// SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
// e2size); e2size);
// break; break;
// case ARMul_AddrExceptnV: /* Address Exception */ case ARMul_AddrExceptnV: /* Address Exception */
// SETABORT (IBIT, SVC26MODE, isize); SETABORT (IBIT, SVC26MODE, isize);
// break; break;
// case ARMul_IRQV: /* IRQ */ case ARMul_IRQV: /* IRQ */
// //chy 2003-09-02 the if sentence seems no use //chy 2003-09-02 the if sentence seems no use
//#if 0 #if 0
// if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
// || (temp & ARMul_CP13_R0_IRQ)) || (temp & ARMul_CP13_R0_IRQ))
//#endif #endif
// SETABORT (IBIT, SETABORT (IBIT,
// state->prog32Sig ? IRQ32MODE : IRQ26MODE, state->prog32Sig ? IRQ32MODE : IRQ26MODE,
// esize); esize);
// break; break;
// case ARMul_FIQV: /* FIQ */ case ARMul_FIQV: /* FIQ */
// //chy 2003-09-02 the if sentence seems no use //chy 2003-09-02 the if sentence seems no use
//#if 0 #if 0
// if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
// || (temp & ARMul_CP13_R0_FIQ)) || (temp & ARMul_CP13_R0_FIQ))
//#endif #endif
// SETABORT (INTBITS, SETABORT (INTBITS,
// state->prog32Sig ? FIQ32MODE : FIQ26MODE, state->prog32Sig ? FIQ32MODE : FIQ26MODE,
// esize); esize);
// break; break;
// } }
//
// if (ARMul_MODE32BIT) { if (ARMul_MODE32BIT) {
// if (state->mmu.control & CONTROL_VECTOR) if (state->mmu.control & CONTROL_VECTOR)
// vector += 0xffff0000; //for v4 high exception address vector += 0xffff0000; //for v4 high exception address
// if (state->vector_remap_flag) if (state->vector_remap_flag)
// vector += state->vector_remap_addr; /* support some remap function in LPC processor */ vector += state->vector_remap_addr; /* support some remap function in LPC processor */
// ARMul_SetR15 (state, vector); ARMul_SetR15 (state, vector);
// } }
// else else
// ARMul_SetR15 (state, R15CCINTMODE | vector); ARMul_SetR15 (state, R15CCINTMODE | vector);
//} }

View File

@ -45,55 +45,51 @@ mmu_init (ARMul_State * state)
state->mmu.process_id = 0; state->mmu.process_id = 0;
switch (state->cpu->cpu_val & state->cpu->cpu_mask) { switch (state->cpu->cpu_val & state->cpu->cpu_mask) {
case SA1100: //case SA1100:
case SA1110: //case SA1110:
SKYEYE_INFO("SKYEYE: use sa11xx mmu ops\n"); // NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
state->mmu.ops = sa_mmu_ops; // state->mmu.ops = sa_mmu_ops;
break; // break;
case PXA250: //case PXA250:
case PXA270: //xscale //case PXA270: //xscale
SKYEYE_INFO ("SKYEYE: use xscale mmu ops\n"); // NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
state->mmu.ops = xscale_mmu_ops; // state->mmu.ops = xscale_mmu_ops;
break; // break;
case 0x41807200: //arm720t //case 0x41807200: //arm720t
case 0x41007700: //arm7tdmi //case 0x41007700: //arm7tdmi
case 0x41007100: //arm7100 //case 0x41007100: //arm7100
SKYEYE_INFO ( "SKYEYE: use arm7100 mmu ops\n"); // NOTICE_LOG(ARM11, "SKYEYE: use arm7100 mmu ops\n");
state->mmu.ops = arm7100_mmu_ops; // state->mmu.ops = arm7100_mmu_ops;
break; // break;
case 0x41009200: //case 0x41009200:
SKYEYE_INFO ("SKYEYE: use arm920t mmu ops\n"); // NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
state->mmu.ops = arm920t_mmu_ops; // state->mmu.ops = arm920t_mmu_ops;
break; // break;
case 0x41069260: //case 0x41069260:
SKYEYE_INFO ("SKYEYE: use arm926ejs mmu ops\n"); // NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
state->mmu.ops = arm926ejs_mmu_ops; // state->mmu.ops = arm926ejs_mmu_ops;
break; // break;
/* case 0x560f5810: */ /* case 0x560f5810: */
case 0x0007b000: case 0x0007b000:
SKYEYE_INFO ("SKYEYE: use arm11jzf-s mmu ops\n"); NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n");
state->mmu.ops = arm1176jzf_s_mmu_ops; //state->mmu.ops = arm1176jzf_s_mmu_ops;
_dbg_assert_msg_(ARM11, false, "ImplementMe: arm1176jzf_s_mmu_ops!");
break; break;
case 0xc090:
SKYEYE_INFO ("SKYEYE: use cortex_a9 mmu ops\n");
state->mmu.ops = cortex_a9_mmu_ops;
break;
default: default:
fprintf (stderr, ERROR_LOG (ARM11,
"SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n",
state->cpu->cpu_val & state->cpu->cpu_mask); state->cpu->cpu_val & state->cpu->cpu_mask);
skyeye_exit (-1);
break; break;
}; };
ret = state->mmu.ops.init (state); ret = state->mmu.ops.init (state);
state->mmu_inited = (ret == 0); state->mmu_inited = (ret == 0);
/* initialize mmu_read and mmu_write for disassemble */ /* initialize mmu_read and mmu_write for disassemble */
skyeye_config_t *config = get_current_config(); //skyeye_config_t *config = get_current_config();
generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); //generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
arch_instance->mmu_read = arm_mmu_read; //arch_instance->mmu_read = arm_mmu_read;
arch_instance->mmu_write = arm_mmu_write; //arch_instance->mmu_write = arm_mmu_write;
return ret; return ret;
} }
@ -201,41 +197,43 @@ mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr)
return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr));
} }
/* dis_mmu_read for disassemble */ //
exception_t arm_mmu_read(short size, generic_address_t addr, uint32_t * value) //
{ ///* dis_mmu_read for disassemble */
ARMul_State *state; //exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
ARM_CPU_State *cpu = get_current_cpu(); //{
state = &cpu->core[0]; // ARMul_State *state;
switch(size){ // ARM_CPU_State *cpu = get_current_cpu();
case 8: // state = &cpu->core[0];
MMU_OPS.read_byte (state, addr, value); // switch(size){
break; // case 8:
case 16: // MMU_OPS.read_byte (state, addr, value);
case 32: // break;
break; // case 16:
default: // case 32:
printf("In %s error size %d Line %d\n", __func__, size, __LINE__); // break;
break; // default:
} // ERROR_LOG(ARM11, "Error size %d", size);
return No_exp; // break;
} // }
/* dis_mmu_write for disassemble */ // return No_exp;
exception_t arm_mmu_write(short size, generic_address_t addr, uint32_t *value) //}
{ ///* dis_mmu_write for disassemble */
ARMul_State *state; //exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
ARM_CPU_State *cpu = get_current_cpu(); //{
state = &cpu->core[0]; // ARMul_State *state;
switch(size){ // ARM_CPU_State *cpu = get_current_cpu();
case 8: // state = &cpu->core[0];
MMU_OPS.write_byte (state, addr, value); // switch(size){
break; // case 8:
case 16: // MMU_OPS.write_byte (state, addr, value);
case 32: // break;
break; // case 16:
default: // case 32:
printf("In %s error size %d Line %d\n", __func__, size, __LINE__); // break;
break; // default:
} // printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
return No_exp; // break;
} // }
// return No_exp;
//}

742
src/core/src/arm/armos.cpp Normal file
View File

@ -0,0 +1,742 @@
/* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
This program 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.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file contains a model of Demon, ARM Ltd's Debug Monitor,
including all the SWI's required to support the C library. The code in
it is not really for the faint-hearted (especially the abort handling
code), but it is a complete example. Defining NOOS will disable all the
fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
0x11 to halt the emulator. */
//chy 2005-09-12 disable below line
//#include "config.h"
#include <time.h>
#include <errno.h>
#include <string.h>
#include "skyeye_defs.h"
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64 /* When use 64 bit large file need define it! for stat64*/
#endif
#include <fcntl.h>
#include <sys/stat.h>
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_WRONLY
#define O_WRONLY 1
#endif
#ifndef O_RDWR
#define O_RDWR 2
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef __STDC__
#define unlink(s) remove(s)
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* For SEEK_SET etc */
#endif
#ifdef __riscos
extern int _fisatty (FILE *);
#define isatty_(f) _fisatty(f)
#else
#ifdef __ZTC__
#include <io.h>
#define isatty_(f) isatty((f)->_file)
#else
#ifdef macintosh
#include <ioctl.h>
#define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
#else
#define isatty_(f) isatty (fileno (f))
#endif
#endif
#endif
#include "armdefs.h"
#include "armos.h"
#include "armemu.h"
#ifndef NOOS
#ifndef VALIDATE
/* #ifndef ASIM */
//chy 2005-09-12 disable below line
//#include "armfpe.h"
/* #endif */
#endif
#endif
#define DUMP_SYSCALL 0
#define dump(...) do { if (DUMP_SYSCALL) printf(__VA_ARGS__); } while(0)
//#define debug(...) printf(__VA_ARGS__);
#define debug(...) ;
extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
#ifndef FOPEN_MAX
#define FOPEN_MAX 64
#endif
/***************************************************************************\
* OS private Information *
\***************************************************************************/
unsigned arm_dyncom_SWI(ARMul_State * state, ARMword number)
{
return ARMul_OSHandleSWI(state, number);
}
//mmap_area_t *mmap_global = NULL;
static int translate_open_mode[] = {
O_RDONLY, /* "r" */
O_RDONLY + O_BINARY, /* "rb" */
O_RDWR, /* "r+" */
O_RDWR + O_BINARY, /* "r+b" */
O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
O_WRONLY + O_APPEND + O_CREAT, /* "a" */
O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
O_RDWR + O_APPEND + O_CREAT, /* "a+" */
O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
};
//
//static void
//SWIWrite0 (ARMul_State * state, ARMword addr)
//{
// ARMword temp;
//
// //while ((temp = ARMul_ReadByte (state, addr++)) != 0)
// while(1){
// mem_read(8, addr++, &temp);
// if(temp != 0)
// (void) fputc ((char) temp, stdout);
// else
// break;
// }
//}
//
//static void
//WriteCommandLineTo (ARMul_State * state, ARMword addr)
//{
// ARMword temp;
// char *cptr = state->CommandLine;
// if (cptr == NULL)
// cptr = "\0";
// do {
// temp = (ARMword) * cptr++;
// //ARMul_WriteByte (state, addr++, temp);
// mem_write(8, addr++, temp);
// }
// while (temp != 0);
//}
//
//static void
//SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
//{
// char dummy[2000];
// int flags;
// int i;
//
// for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++);
// assert(SWIflags< (sizeof(translate_open_mode)/ sizeof(translate_open_mode[0])));
// /* Now we need to decode the Demon open mode */
// flags = translate_open_mode[SWIflags];
// flags = SWIflags;
//
// /* Filename ":tt" is special: it denotes stdin/out */
// if (strcmp (dummy, ":tt") == 0) {
// if (flags == O_RDONLY) /* opening tty "r" */
// state->Reg[0] = 0; /* stdin */
// else
// state->Reg[0] = 1; /* stdout */
// }
// else {
// state->Reg[0] = (int) open (dummy, flags, 0666);
// }
//}
//
//static void
//SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
//{
// int res;
// int i;
// char *local = (char*) malloc (len);
//
// if (local == NULL) {
// fprintf (stderr,
// "sim: Unable to read 0x%ulx bytes - out of memory\n",
// len);
// return;
// }
//
// res = read (f, local, len);
// if (res > 0)
// for (i = 0; i < res; i++)
// //ARMul_WriteByte (state, ptr + i, local[i]);
// mem_write(8, ptr + i, local[i]);
// free (local);
// //state->Reg[0] = res == -1 ? -1 : len - res;
// state->Reg[0] = res;
//}
//
//static void
//SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
//{
// int res;
// ARMword i;
// char *local = malloc (len);
//
// if (local == NULL) {
// fprintf (stderr,
// "sim: Unable to write 0x%lx bytes - out of memory\n",
// (long unsigned int) len);
// return;
// }
//
// for (i = 0; i < len; i++){
// //local[i] = ARMul_ReadByte (state, ptr + i);
// ARMword data;
// mem_read(8, ptr + i, &data);
// local[i] = data & 0xFF;
// }
//
// res = write (f, local, len);
// //state->Reg[0] = res == -1 ? -1 : len - res;
// state->Reg[0] = res;
// free (local);
//}
//static void
//SWIflen (ARMul_State * state, ARMword fh)
//{
// ARMword addr;
//
// if (fh == 0 || fh > FOPEN_MAX) {
// state->Reg[0] = -1L;
// return;
// }
//
// addr = lseek (fh, 0, SEEK_CUR);
//
// state->Reg[0] = lseek (fh, 0L, SEEK_END);
// (void) lseek (fh, addr, SEEK_SET);
//
//}
/***************************************************************************\
* The emulator calls this routine when a SWI instruction is encuntered. The *
* parameter passed is the SWI number (lower 24 bits of the instruction). *
\***************************************************************************/
/* ahe-ykl information is retrieved from elf header and the starting value of
brk_static is in sky_info_t */
/* brk static hold the value of brk */
static uint32_t brk_static = -1;
unsigned
ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
{
number &= 0xfffff;
ARMword addr, temp;
switch (number) {
// case SWI_Syscall:
// if (state->Reg[7] != 0)
// return ARMul_OSHandleSWI(state, state->Reg[7]);
// else
// return FALSE;
// case SWI_Read:
// SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
// return TRUE;
//
// case SWI_GetUID32:
// state->Reg[0] = getuid();
// return TRUE;
//
// case SWI_GetGID32:
// state->Reg[0] = getgid();
// return TRUE;
//
// case SWI_GetEUID32:
// state->Reg[0] = geteuid();
// return TRUE;
//
// case SWI_GetEGID32:
// state->Reg[0] = getegid();
// return TRUE;
//
// case SWI_Write:
// SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
// return TRUE;
//
// case SWI_Open:
// SWIopen (state, state->Reg[0], state->Reg[1]);
// return TRUE;
//
// case SWI_Close:
// state->Reg[0] = close (state->Reg[0]);
// return TRUE;
//
// case SWI_Seek:{
// /* We must return non-zero for failure */
// state->Reg[0] =
// lseek (state->Reg[0], state->Reg[1],
// SEEK_SET);
// return TRUE;
// }
//
// case SWI_ExitGroup:
// case SWI_Exit:
// {
// struct timeval tv;
// //gettimeofday(&tv,NULL);
// //printf("In %s, %d sec, %d usec\n", __FUNCTION__, tv.tv_sec, tv.tv_usec);
// printf("passed %d sec, %lld usec\n", get_clock_sec(), get_clock_us());
//
// /* quit here */
// run_command("quit");
// return TRUE;
// }
// case SWI_Times:{
// uint32_t dest = state->Reg[0];
// struct tms now;
// struct target_tms32 nowret;
//
// uint32_t ret = times(&now);
//
// if (ret == -1){
// debug("syscall %s error %d\n", "SWI_Times", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
//
// nowret.tms_cstime = now.tms_cstime;
// nowret.tms_cutime = now.tms_cutime;
// nowret.tms_stime = now.tms_stime;
// nowret.tms_utime = now.tms_utime;
//
// uint32_t offset;
// for (offset = 0; offset < sizeof(nowret); offset++) {
// bus_write(8, dest + offset, *((uint8_t *) &nowret + offset));
// }
//
// state->Reg[0] = ret;
// return TRUE;
// }
//
// case SWI_Gettimeofday: {
// uint32_t dest1 = state->Reg[0];
// uint32_t dest2 = state->Reg[1]; // Unsure of this
// struct timeval val;
// struct timezone zone;
// struct target_timeval32 valret;
// struct target_timezone32 zoneret;
//
// uint32_t ret = gettimeofday(&val, &zone);
// valret.tv_sec = val.tv_sec;
// valret.tv_usec = val.tv_usec;
// zoneret.tz_dsttime = zoneret.tz_dsttime;
// zoneret.tz_minuteswest = zoneret.tz_minuteswest;
//
// if (ret == -1){
// debug("syscall %s error %d\n", "SWI_Gettimeofday", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
//
// uint32_t offset;
// if (dest1) {
// for (offset = 0; offset < sizeof(valret); offset++) {
// bus_write(8, dest1 + offset, *((uint8_t *) &valret + offset));
// }
// state->Reg[0] = ret;
// }
// if (dest2) {
// for (offset = 0; offset < sizeof(zoneret); offset++) {
// bus_write(8, dest2 + offset, *((uint8_t *) &zoneret + offset));
// }
// state->Reg[0] = ret;
// }
//
// return TRUE;
// }
// case SWI_Brk:
// /* initialize brk value */
// /* suppose that brk_static doesn't reach 0xffffffff... */
// if (brk_static == -1) {
// brk_static = (get_skyeye_pref()->info).brk;
// }
//
// /* FIXME there might be a need to do a mmap */
//
// if(state->Reg[0]){
// if (get_skyeye_exec_info()->mmap_access) {
// /* if new brk is greater than current brk, allocate memory */
// if (state->Reg[0] > brk_static) {
// uint32_t ret = mmap( (void *) brk_static, state->Reg[0] - brk_static,
// PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0 );
// if (ret != MAP_FAILED)
// brk_static = ret;
// }
// }
// brk_static = state->Reg[0];
// //state->Reg[0] = 0; /* FIXME return value of brk set to be the address on success */
// } else {
// state->Reg[0] = brk_static;
// }
// return TRUE;
//
// case SWI_Break:
// state->Emulate = FALSE;
// return TRUE;
//
// case SWI_Mmap:{
// int addr = state->Reg[0];
// int len = state->Reg[1];
// int prot = state->Reg[2];
// int flag = state->Reg[3];
// int fd = state->Reg[4];
// int offset = state->Reg[5];
// mmap_area_t *area = new_mmap_area(addr, len);
// state->Reg[0] = area->bank.addr;
// //printf("syscall %d mmap(0x%x,%x,0x%x,0x%x,%d,0x%x) = 0x%x\n",\
// SWI_Mmap, addr, len, prot, flag, fd, offset, state->Reg[0]);
// return TRUE;
// }
//
// case SWI_Munmap:
// state->Reg[0] = 0;
// return TRUE;
//
// case SWI_Mmap2:{
// int addr = state->Reg[0];
// int len = state->Reg[1];
// int prot = state->Reg[2];
// int flag = state->Reg[3];
// int fd = state->Reg[4];
// int offset = state->Reg[5] * 4096; /* page offset */
// mmap_area_t *area = new_mmap_area(addr, len);
// state->Reg[0] = area->bank.addr;
//
// return TRUE;
// }
//
// case SWI_Breakpoint:
// //chy 2005-09-12 change below line
// //state->EndCondition = RDIError_BreakpointReached;
// //printf ("SKYEYE: in armos.c : should not come here!!!!\n");
// state->EndCondition = 0;
// /*modified by ksh to support breakpoiont*/
// state->Emulate = STOP;
// return (TRUE);
// case SWI_Uname:
// {
// struct utsname *uts = (uintptr_t) state->Reg[0]; /* uname should write data in this address */
// struct utsname utsbuf;
// //printf("Uname size is %x\n", sizeof(utsbuf));
// char *buf;
// uintptr_t sp ; /* used as a temporary address */
//
//#define COPY_UTS_STRING(addr) \
// buf = addr; \
// while(*buf != NULL) { \
// bus_write(8, sp, *buf); \
// sp++; \
// buf++; \
// }
//#define COPY_UTS(field) /*printf("%s: %s at %p\n", #field, utsbuf.field, uts->field);*/ \
// sp = (uintptr_t) uts->field; \
// COPY_UTS_STRING((&utsbuf)->field);
//
// if (uname(&utsbuf) < 0) {
// printf("syscall uname: utsname error\n");
// state->Reg[0] = -1;
// return FALSE;
// }
//
// /* FIXME for now, this is just the host system call
// Some data should be missing, as it depends on
// the version of utsname */
// COPY_UTS(sysname);
// COPY_UTS(nodename);
// COPY_UTS(release);
// COPY_UTS(version);
// COPY_UTS(machine);
//
// state->Reg[0] = 0;
// return TRUE;
// }
// case SWI_Fcntl:
// {
// uint32_t fd = state->Reg[0];
// uint32_t cmd = state->Reg[1];
// uint32_t arg = state->Reg[2];
// uint32_t ret;
//
// switch(cmd){
// case (F_GETFD):
// {
// ret = fcntl(fd, cmd, arg);
// //printf("syscall fcntl for getfd not implemented, ret %d\n", ret);
// state->Reg[0] = ret;
// return FALSE;
// }
// default:
// break;
// }
//
// printf("syscall fcntl unimplemented fd %x cmd %x\n", fd, cmd);
// state->Reg[0] = -1;
// return FALSE;
//
// }
// case SWI_Fstat64:
// {
// uint32_t dest = state->Reg[1];
// uint32_t fd = state->Reg[0];
// struct stat64 statbuf;
// struct target_stat64 statret;
// memset(&statret, 0, sizeof(struct target_stat64));
// uint32_t ret = fstat64(fd, &statbuf);
//
// if (ret == -1){
// printf("syscall %s returned error\n", "SWI_Fstat");
// state->Reg[0] = ret;
// return FALSE;
// }
//
// /* copy statbuf to the process memory space
// FIXME can't say if endian has an effect here */
// uint32_t offset;
// //printf("Fstat system is size %x\n", sizeof(statbuf));
// //printf("Fstat target is size %x\n", sizeof(statret));
//
// /* we copy system structure data stat64 into arm fixed size structure target_stat64 */
// statret.st_dev = statbuf.st_dev;
// statret.st_ino = statbuf.st_ino;
// statret.st_mode = statbuf.st_mode;
// statret.st_nlink = statbuf.st_nlink;
// statret.st_uid = statbuf.st_uid;
// statret.st_gid = statbuf.st_gid;
// statret.st_rdev = statbuf.st_rdev;
// statret.st_size = statbuf.st_size;
// statret.st_blksize = statbuf.st_blksize;
// statret.st_blocks = statbuf.st_blocks;
// statret.st32_atime = statbuf.st_atime;
// statret.st32_mtime = statbuf.st_mtime;
// statret.st32_ctime = statbuf.st_ctime;
//
// for (offset = 0; offset < sizeof(statret); offset++) {
// bus_write(8, dest + offset, *((uint8_t *) &statret + offset));
// }
//
// state->Reg[0] = ret;
// return TRUE;
// }
// case SWI_Set_tls:
// {
// //printf("syscall set_tls unimplemented\n");
// state->mmu.thread_uro_id = state->Reg[0];
// state->CP15[CP15_THREAD_URO - CP15_BASE] = state->Reg[0];
// state->Reg[0] = 0;
// return FALSE;
// }
//#if 0
// case SWI_Clock:
// /* return number of centi-seconds... */
// state->Reg[0] =
//#ifdef CLOCKS_PER_SEC
// (CLOCKS_PER_SEC >= 100)
// ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
// : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
//#else
// /* presume unix... clock() returns microseconds */
// (ARMword) (clock () / 10000);
//#endif
// return (TRUE);
//
// case SWI_Time:
// state->Reg[0] = (ARMword) time (NULL);
// return (TRUE);
// case SWI_Flen:
// SWIflen (state, state->Reg[0]);
// return (TRUE);
//
//#endif
default:
_dbg_assert_msg_(ARM11, false, "ImplementMe: ARMul_OSHandleSWI!");
return (FALSE);
}
}
//
///**
// * @brief For mmap syscall.A mmap_area is a memory bank. Get from ppc.
// */
//static mmap_area_t* new_mmap_area(int sim_addr, int len){
// mmap_area_t *area = (mmap_area_t *)malloc(sizeof(mmap_area_t));
// if(area == NULL){
// printf("error, failed %s\n",__FUNCTION__);
// exit(0);
// }
//#if FAST_MEMORY
// if (mmap_next_base == -1)
// {
// mmap_next_base = get_skyeye_exec_info()->brk;
// }
//#endif
//
// memset(area, 0x0, sizeof(mmap_area_t));
// area->bank.addr = mmap_next_base;
// area->bank.len = len;
// area->bank.bank_write = mmap_mem_write;
// area->bank.bank_read = mmap_mem_read;
// area->bank.type = MEMTYPE_RAM;
// area->bank.objname = "mmap";
// addr_mapping(&area->bank);
//
//#if FAST_MEMORY
// if (get_skyeye_exec_info()->mmap_access)
// {
// /* FIXME check proper flags */
// /* FIXME we may delete the need of banks up there */
// uint32_t ret = mmap(mmap_next_base, len, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// mmap_next_base = ret;
// }
// area->mmap_addr = (uint8_t*)get_dma_addr(mmap_next_base);
//#else
// area->mmap_addr = malloc(len);
// if(area->mmap_addr == NULL){
// printf("error mmap malloc\n");
// exit(0);
// }
// memset(area->mmap_addr, 0x0, len);
//#endif
//
// area->next = NULL;
// if(mmap_global){
// area->next = mmap_global->next;
// mmap_global->next = area;
// }else{
// mmap_global = area;
// }
// mmap_next_base = mmap_next_base + len;
// return area;
//}
//
//static mmap_area_t *get_mmap_area(int addr){
// mmap_area_t *tmp = mmap_global;
// while(tmp){
// if ((tmp->bank.addr <= addr) && (tmp->bank.addr + tmp->bank.len > addr)){
// return tmp;
// }
// tmp = tmp->next;
// }
// printf("cannot get mmap area:addr=0x%x\n", addr);
// return NULL;
//}
//
///**
// * @brief the mmap_area bank write function. Get from ppc.
// *
// * @param size size to write, 8/16/32
// * @param addr address to write
// * @param value value to write
// *
// * @return sucess return 1,otherwise 0.
// */
//static char mmap_mem_write(short size, int addr, uint32_t value){
// mmap_area_t *area_tmp = get_mmap_area(addr);
// mem_bank_t *bank_tmp = &area_tmp->bank;
// int offset = addr - bank_tmp->addr;
// switch(size){
// case 8:{
// //uint8_t value_endian = value;
// uint8_t value_endian = (uint8_t)value;
// *(uint8_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// case 16:{
// //uint16_t value_endian = half_to_BE((uint16_t)value);
// uint16_t value_endian = ((uint16_t)value);
// *(uint16_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// case 32:{
// //uint32_t value_endian = word_to_BE((uint32_t)value);
// uint32_t value_endian = ((uint32_t)value);
// *(uint32_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
// break;
// }
// default:
// printf("invalid size %d\n",size);
// return 0;
// }
// return 1;
//}
//
///**
// * @brief the mmap_area bank read function. Get from ppc.
// *
// * @param size size to read, 8/16/32
// * @param addr address to read
// * @param value value to read
// *
// * @return sucess return 1,otherwise 0.
// */
//static char mmap_mem_read(short size, int addr, uint32_t * value){
// mmap_area_t *area_tmp = get_mmap_area(addr);
// mem_bank_t *bank_tmp = &area_tmp->bank;
// int offset = addr - bank_tmp->addr;
// switch(size){
// case 8:{
// //*(uint8_t *)value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
// *value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
// break;
// }
// case 16:{
// //*(uint16_t *)value = half_from_BE(*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// *value = (*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint16_t*)value);
// break;
// }
// case 32:
// //*value = (uint32_t)word_from_BE(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// *value = (uint32_t)(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
// debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
// break;
// default:
// printf("invalid size %d\n",size);
// return 0;
// }
// return 1;
//}

View File

@ -0,0 +1,953 @@
/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
This program 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.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "armdefs.h"
#include "armemu.h"
//#include "ansidecl.h"
#include "skyeye_defs.h"
unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg,
unsigned cpnum);
//extern int skyeye_instr_debug;
/* Definitions for the support routines. */
static ARMword ModeToBank (ARMword);
static void EnvokeList (ARMul_State *, unsigned int, unsigned int);
struct EventNode
{ /* An event list node. */
unsigned (*func) (ARMul_State *); /* The function to call. */
struct EventNode *next;
};
/* This routine returns the value of a register from a mode. */
ARMword
ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
{
mode &= MODEBITS;
if (mode != state->Mode)
return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
else
return (state->Reg[reg]);
}
/* This routine sets the value of a register for a mode. */
void
ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
{
mode &= MODEBITS;
if (mode != state->Mode)
state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
else
state->Reg[reg] = value;
}
/* This routine returns the value of the PC, mode independently. */
ARMword
ARMul_GetPC (ARMul_State * state)
{
if (state->Mode > SVC26MODE)
return state->Reg[15];
else
return R15PC;
}
/* This routine returns the value of the PC, mode independently. */
ARMword
ARMul_GetNextPC (ARMul_State * state)
{
if (state->Mode > SVC26MODE)
return state->Reg[15] + isize;
else
return (state->Reg[15] + isize) & R15PCBITS;
}
/* This routine sets the value of the PC. */
void
ARMul_SetPC (ARMul_State * state, ARMword value)
{
if (ARMul_MODE32BIT)
state->Reg[15] = value & PCBITS;
else
state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
FLUSHPIPE;
}
/* This routine returns the value of register 15, mode independently. */
ARMword
ARMul_GetR15 (ARMul_State * state)
{
if (state->Mode > SVC26MODE)
return (state->Reg[15]);
else
return (R15PC | ECC | ER15INT | EMODE);
}
/* This routine sets the value of Register 15. */
void
ARMul_SetR15 (ARMul_State * state, ARMword value)
{
if (ARMul_MODE32BIT)
state->Reg[15] = value & PCBITS;
else {
state->Reg[15] = value;
ARMul_R15Altered (state);
}
FLUSHPIPE;
}
/* This routine returns the value of the CPSR. */
ARMword
ARMul_GetCPSR (ARMul_State * state)
{
//chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
//return (CPSR | state->Cpsr); for gdb20030716
return (CPSR); //had be tested in old skyeye with gdb5.0-5.3
}
/* This routine sets the value of the CPSR. */
void
ARMul_SetCPSR (ARMul_State * state, ARMword value)
{
state->Cpsr = value;
ARMul_CPSRAltered (state);
}
/* This routine does all the nasty bits involved in a write to the CPSR,
including updating the register bank, given a MSR instruction. */
void
ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
{
state->Cpsr = ARMul_GetCPSR (state);
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
/* In user mode, only write flags. */
if (BIT (16))
SETPSR_C (state->Cpsr, rhs);
if (BIT (17))
SETPSR_X (state->Cpsr, rhs);
if (BIT (18))
SETPSR_S (state->Cpsr, rhs);
}
if (BIT (19))
SETPSR_F (state->Cpsr, rhs);
ARMul_CPSRAltered (state);
}
/* Get an SPSR from the specified mode. */
ARMword
ARMul_GetSPSR (ARMul_State * state, ARMword mode)
{
ARMword bank = ModeToBank (mode & MODEBITS);
if (!BANK_CAN_ACCESS_SPSR (bank))
return ARMul_GetCPSR (state);
return state->Spsr[bank];
}
/* This routine does a write to an SPSR. */
void
ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
{
ARMword bank = ModeToBank (mode & MODEBITS);
if (BANK_CAN_ACCESS_SPSR (bank))
state->Spsr[bank] = value;
}
/* This routine does a write to the current SPSR, given an MSR instruction. */
void
ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
{
if (BANK_CAN_ACCESS_SPSR (state->Bank)) {
if (BIT (16))
SETPSR_C (state->Spsr[state->Bank], rhs);
if (BIT (17))
SETPSR_X (state->Spsr[state->Bank], rhs);
if (BIT (18))
SETPSR_S (state->Spsr[state->Bank], rhs);
if (BIT (19))
SETPSR_F (state->Spsr[state->Bank], rhs);
}
}
/* This routine updates the state of the emulator after the Cpsr has been
changed. Both the processor flags and register bank are updated. */
void
ARMul_CPSRAltered (ARMul_State * state)
{
ARMword oldmode;
if (state->prog32Sig == LOW)
state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
oldmode = state->Mode;
if (state->Mode != (state->Cpsr & MODEBITS)) {
state->Mode =
ARMul_SwitchMode (state, state->Mode,
state->Cpsr & MODEBITS);
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
}
//state->Cpsr &= ~MODEBITS;
ASSIGNINT (state->Cpsr & INTBITS);
//state->Cpsr &= ~INTBITS;
ASSIGNN ((state->Cpsr & NBIT) != 0);
//state->Cpsr &= ~NBIT;
ASSIGNZ ((state->Cpsr & ZBIT) != 0);
//state->Cpsr &= ~ZBIT;
ASSIGNC ((state->Cpsr & CBIT) != 0);
//state->Cpsr &= ~CBIT;
ASSIGNV ((state->Cpsr & VBIT) != 0);
//state->Cpsr &= ~VBIT;
ASSIGNS ((state->Cpsr & SBIT) != 0);
//state->Cpsr &= ~SBIT;
#ifdef MODET
ASSIGNT ((state->Cpsr & TBIT) != 0);
//state->Cpsr &= ~TBIT;
#endif
if (oldmode > SVC26MODE) {
if (state->Mode <= SVC26MODE) {
state->Emulate = CHANGEMODE;
state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
}
}
else {
if (state->Mode > SVC26MODE) {
state->Emulate = CHANGEMODE;
state->Reg[15] = R15PC;
}
else
state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
}
}
/* This routine updates the state of the emulator after register 15 has
been changed. Both the processor flags and register bank are updated.
This routine should only be called from a 26 bit mode. */
void
ARMul_R15Altered (ARMul_State * state)
{
if (state->Mode != R15MODE) {
state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
}
if (state->Mode > SVC26MODE)
state->Emulate = CHANGEMODE;
ASSIGNR15INT (R15INT);
ASSIGNN ((state->Reg[15] & NBIT) != 0);
ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
ASSIGNC ((state->Reg[15] & CBIT) != 0);
ASSIGNV ((state->Reg[15] & VBIT) != 0);
}
/* This routine controls the saving and restoring of registers across mode
changes. The regbank matrix is largely unused, only rows 13 and 14 are
used across all modes, 8 to 14 are used for FIQ, all others use the USER
column. It's easier this way. old and new parameter are modes numbers.
Notice the side effect of changing the Bank variable. */
ARMword
ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
{
unsigned i;
ARMword oldbank;
ARMword newbank;
static int revision_value = 53;
oldbank = ModeToBank (oldmode);
newbank = state->Bank = ModeToBank (newmode);
/* Do we really need to do it? */
if (oldbank != newbank) {
if (oldbank == 3 && newbank == 2) {
//printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank);
if (state->NumInstrs >= 5832487) {
// printf("%d, ", state->NumInstrs + revision_value);
// printf("revision_value : %d\n", revision_value);
revision_value ++;
}
}
/* Save away the old registers. */
switch (oldbank) {
case USERBANK:
case IRQBANK:
case SVCBANK:
case ABORTBANK:
case UNDEFBANK:
if (newbank == FIQBANK)
for (i = 8; i < 13; i++)
state->RegBank[USERBANK][i] =
state->Reg[i];
state->RegBank[oldbank][13] = state->Reg[13];
state->RegBank[oldbank][14] = state->Reg[14];
break;
case FIQBANK:
for (i = 8; i < 15; i++)
state->RegBank[FIQBANK][i] = state->Reg[i];
break;
case DUMMYBANK:
for (i = 8; i < 15; i++)
state->RegBank[DUMMYBANK][i] = 0;
break;
default:
abort ();
}
/* Restore the new registers. */
switch (newbank) {
case USERBANK:
case IRQBANK:
case SVCBANK:
case ABORTBANK:
case UNDEFBANK:
if (oldbank == FIQBANK)
for (i = 8; i < 13; i++)
state->Reg[i] =
state->RegBank[USERBANK][i];
state->Reg[13] = state->RegBank[newbank][13];
state->Reg[14] = state->RegBank[newbank][14];
break;
case FIQBANK:
for (i = 8; i < 15; i++)
state->Reg[i] = state->RegBank[FIQBANK][i];
break;
case DUMMYBANK:
for (i = 8; i < 15; i++)
state->Reg[i] = 0;
break;
default:
abort ();
}
}
return newmode;
}
/* Given a processor mode, this routine returns the
register bank that will be accessed in that mode. */
static ARMword
ModeToBank (ARMword mode)
{
static ARMword bankofmode[] = {
USERBANK, FIQBANK, IRQBANK, SVCBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
USERBANK, FIQBANK, IRQBANK, SVCBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
};
if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
return DUMMYBANK;
return bankofmode[mode];
}
/* Returns the register number of the nth register in a reg list. */
unsigned
ARMul_NthReg (ARMword instr, unsigned number)
{
unsigned bit, upto;
for (bit = 0, upto = 0; upto <= number; bit++)
if (BIT (bit))
upto++;
return (bit - 1);
}
/* Assigns the N and Z flags depending on the value of result. */
void
ARMul_NegZero (ARMul_State * state, ARMword result)
{
if (NEG (result)) {
SETN;
CLEARZ;
}
else if (result == 0) {
CLEARN;
SETZ;
}
else {
CLEARN;
CLEARZ;
}
}
/* Compute whether an addition of A and B, giving RESULT, overflowed. */
int
AddOverflow (ARMword a, ARMword b, ARMword result)
{
return ((NEG (a) && NEG (b) && POS (result))
|| (POS (a) && POS (b) && NEG (result)));
}
/* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
int
SubOverflow (ARMword a, ARMword b, ARMword result)
{
return ((NEG (a) && POS (b) && POS (result))
|| (POS (a) && NEG (b) && NEG (result)));
}
/* Assigns the C flag after an addition of a and b to give result. */
void
ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNC ((NEG (a) && NEG (b)) ||
(NEG (a) && POS (result)) || (NEG (b) && POS (result)));
}
/* Assigns the V flag after an addition of a and b to give result. */
void
ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNV (AddOverflow (a, b, result));
}
/* Assigns the C flag after an subtraction of a and b to give result. */
void
ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNC ((NEG (a) && POS (b)) ||
(NEG (a) && POS (result)) || (POS (b) && POS (result)));
}
/* Assigns the V flag after an subtraction of a and b to give result. */
void
ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNV (SubOverflow (a, b, result));
}
/* This function does the work of generating the addresses used in an
LDC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort*/
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
/*
printf
("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address))
INTERNALABORT (address);
cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr,
0);
}
if (cpab == ARMul_CANT) {
/*
printf
("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
CPTAKEABORT;
return;
}
cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
while (cpab == ARMul_INC) {
address += 4;
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
}
//chy 2004-05-25
L_ldc_takeabort:
if (BIT (21)) {
if (!
((state->abortSig || state->Aborted)
&& state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the work of generating the addresses used in an
STC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort */
// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n");
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
/*
printf
("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr,
&data);
}
if (cpab == ARMul_CANT) {
/*
printf
("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
*/
CPTAKEABORT;
return;
}
#ifndef MODE32
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
#endif
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
while (cpab == ARMul_INC) {
address += 4;
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
}
//chy 2004-05-25
L_stc_takeabort:
if (BIT (21)) {
if (!
((state->abortSig || state->Aborted)
&& state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the Busy-Waiting for an MCR instruction. */
void
ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
{
unsigned cpab;
//printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
//chy 2004-07-19 should fix in the future ????!!!!
//printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source);
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return;
}
else
cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr,
source);
}
if (cpab == ARMul_CANT) {
printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
}
}
/* This function does the Busy-Waiting for an MCRR instruction. */
void
ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2)
{
unsigned cpab;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT,
instr, 0, 0);
return;
}
else
cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr,
source1, source2);
}
if (cpab == ARMul_CANT) {
printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
}
}
/* This function does the Busy-Waiting for an MRC instruction. */
ARMword
ARMul_MRC (ARMul_State * state, ARMword instr)
{
unsigned cpab;
ARMword result = 0;
//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
//chy 2004-07-19 should fix in the future????!!!!
//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
ARMul_UndefInstr (state, instr);
return -1;
}
cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0);
return (0);
}
else
cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr,
&result);
}
if (cpab == ARMul_CANT) {
printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
/* Parent will destroy the flags otherwise. */
result = ECC;
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
ARMul_Icycles (state, 1, 0);
}
return result;
}
/* This function does the Busy-Waiting for an MRRC instruction. (to verify) */
void
ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2)
{
unsigned cpab;
ARMword result1 = 0;
ARMword result2 = 0;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT,
instr, 0, 0);
return;
}
else
cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr,
&result1, &result2);
}
if (cpab == ARMul_CANT) {
printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else {
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
ARMul_Icycles (state, 1, 0);
}
*dest1 = result1;
*dest2 = result2;
}
/* This function does the Busy-Waiting for an CDP instruction. */
void
ARMul_CDP (ARMul_State * state, ARMword instr)
{
unsigned cpab;
if (!CP_ACCESS_ALLOWED (state, CPNum)) {
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
while (cpab == ARMul_BUSY) {
ARMul_Icycles (state, 1, 0);
if (IntPending (state)) {
cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT,
instr);
return;
}
else
cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
}
if (cpab == ARMul_CANT)
ARMul_Abort (state, ARMul_UndefinedInstrV);
else
BUSUSEDN;
}
/* This function handles Undefined instructions, as CP isntruction. */
void
ARMul_UndefInstr (ARMul_State * state, ARMword instr)
{
ERROR_LOG(ARM11, "Undefined instruction!! Instr: 0x%x", instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
/* Return TRUE if an interrupt is pending, FALSE otherwise. */
unsigned
IntPending (ARMul_State * state)
{
/* Any exceptions. */
if (state->NresetSig == LOW) {
ARMul_Abort (state, ARMul_ResetV);
return TRUE;
}
else if (!state->NfiqSig && !FFLAG) {
ARMul_Abort (state, ARMul_FIQV);
return TRUE;
}
else if (!state->NirqSig && !IFLAG) {
ARMul_Abort (state, ARMul_IRQV);
return TRUE;
}
return FALSE;
}
/* Align a word access to a non word boundary. */
ARMword
ARMul_Align (ARMul_State *state, ARMword address, ARMword data)
{
/* This code assumes the address is really unaligned,
as a shift by 32 is undefined in C. */
address = (address & 3) << 3; /* Get the word address. */
return ((data >> address) | (data << (32 - address))); /* rot right */
}
/* This routine is used to call another routine after a certain number of
cycles have been executed. The first parameter is the number of cycles
delay before the function is called, the second argument is a pointer
to the function. A delay of zero doesn't work, just call the function. */
void
ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay,
unsigned (*what) (ARMul_State *))
{
unsigned int when;
struct EventNode *event;
if (state->EventSet++ == 0)
state->Now = ARMul_Time (state);
when = (state->Now + delay) % EVENTLISTSIZE;
event = (struct EventNode *) malloc (sizeof (struct EventNode));
_dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n");
event->func = what;
event->next = *(state->EventPtr + when);
*(state->EventPtr + when) = event;
}
/* This routine is called at the beginning of
every cycle, to envoke scheduled events. */
void
ARMul_EnvokeEvent (ARMul_State * state)
{
static unsigned int then;
then = state->Now;
state->Now = ARMul_Time (state) % EVENTLISTSIZE;
if (then < state->Now)
/* Schedule events. */
EnvokeList (state, then, state->Now);
else if (then > state->Now) {
/* Need to wrap around the list. */
EnvokeList (state, then, EVENTLISTSIZE - 1L);
EnvokeList (state, 0L, state->Now);
}
}
/* Envokes all the entries in a range. */
static void
EnvokeList (ARMul_State * state, unsigned int from, unsigned int to)
{
for (; from <= to; from++) {
struct EventNode *anevent;
anevent = *(state->EventPtr + from);
while (anevent) {
(anevent->func) (state);
state->EventSet--;
anevent = anevent->next;
}
*(state->EventPtr + from) = NULL;
}
}
/* This routine is returns the number of clock ticks since the last reset. */
unsigned int
ARMul_Time (ARMul_State * state)
{
return (state->NumScycles + state->NumNcycles +
state->NumIcycles + state->NumCcycles + state->NumFcycles);
}

View File

@ -0,0 +1,680 @@
/* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
This program 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.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file contains a complete ARMulator memory model, modelling a
"virtual memory" system. A much simpler model can be found in armfast.c,
and that model goes faster too, but has a fixed amount of memory. This
model's memory has 64K pages, allocated on demand from a 64K entry page
table. The routines PutWord and GetWord implement this. Pages are never
freed as they might be needed again. A single area of memory may be
defined to generate aborts. */
#include "armdefs.h"
#include "skyeye_defs.h"
//#include "code_cov.h"
#ifdef VALIDATE /* for running the validate suite */
#define TUBE 48 * 1024 * 1024 /* write a char on the screen */
#define ABORTS 1
#endif
/* #define ABORTS */
#ifdef ABORTS /* the memory system will abort */
/* For the old test suite Abort between 32 Kbytes and 32 Mbytes
For the new test suite Abort between 8 Mbytes and 26 Mbytes */
/* #define LOWABORT 32 * 1024
#define HIGHABORT 32 * 1024 * 1024 */
#define LOWABORT 8 * 1024 * 1024
#define HIGHABORT 26 * 1024 * 1024
#endif
#define NUMPAGES 64 * 1024
#define PAGESIZE 64 * 1024
#define PAGEBITS 16
#define OFFSETBITS 0xffff
//chy 2003-08-19: seems no use ????
int SWI_vector_installed = FALSE;
extern ARMword skyeye_cachetype;
/***************************************************************************\
* Get a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetByte (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetByte fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Get a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetHalfWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: GetHalfWord fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Get a Word from Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
GetWord (ARMul_State * state, ARMword address, ARMword * data)
{
fault_t fault;
fault = mmu_read_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_read_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
//2003-07-10 chy: lyh change
/****************************************************************************\
* Load a Instrion Word into Virtual Memory *
\****************************************************************************/
static fault_t
LoadInstr (ARMul_State * state, ARMword address, ARMword * instr)
{
fault_t fault;
fault = mmu_load_instr (state, address, instr);
return fault;
//if (fault)
// log_msg("load_instr fault = %d, address = %x\n", fault, address);
}
/***************************************************************************\
* Put a byte into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_byte (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutByte fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a halfword into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_halfword (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
// printf("SKYEYE: PutHalfWord fault %d \n", fault);
}
return fault;
}
/***************************************************************************\
* Put a Word into Virtual Memory, maybe allocating the page *
\***************************************************************************/
static fault_t
PutWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = mmu_write_word (state, address, data);
if (fault) {
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
#if 0
/* XXX */ extern int hack;
hack = 1;
#endif
#if 0
printf ("mmu_write_word at 0x%08x: ", address);
switch (fault) {
case ALIGNMENT_FAULT:
printf ("ALIGNMENT_FAULT");
break;
case SECTION_TRANSLATION_FAULT:
printf ("SECTION_TRANSLATION_FAULT");
break;
case PAGE_TRANSLATION_FAULT:
printf ("PAGE_TRANSLATION_FAULT");
break;
case SECTION_DOMAIN_FAULT:
printf ("SECTION_DOMAIN_FAULT");
break;
case SECTION_PERMISSION_FAULT:
printf ("SECTION_PERMISSION_FAULT");
break;
case SUBPAGE_PERMISSION_FAULT:
printf ("SUBPAGE_PERMISSION_FAULT");
break;
default:
printf ("Unrecognized fault number!");
}
printf ("\tpc = 0x%08x\n", state->Reg[15]);
#endif
}
return fault;
}
/***************************************************************************\
* Initialise the memory interface *
\***************************************************************************/
unsigned
ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize)
{
return TRUE;
}
/***************************************************************************\
* Remove the memory interface *
\***************************************************************************/
void
ARMul_MemoryExit (ARMul_State * state)
{
}
/***************************************************************************\
* ReLoad Instruction *
\***************************************************************************/
ARMword
ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
#if 0
/* do profiling for code coverage */
if (skyeye_config.code_cov.prof_on)
cov_prof(EXEC_FLAG, address);
#endif
#if 1
if ((isize == 2) && (address & 0x2)) {
ARMword lo, hi;
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address, &lo);
else
fault = LoadInstr (state, address, &lo);
#if 0
if (!fault) {
if (!(skyeye_cachetype == INSTCACHE))
fault = GetHalfWord (state, address + isize, &hi);
else
fault = LoadInstr (state, address + isize, &hi);
}
#endif
if (fault) {
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return lo;
#if 0
if (state->bigendSig == HIGH)
return (lo << 16) | (hi >> 16);
else
return ((hi & 0xFFFF) << 16) | (lo >> 16);
#endif
}
#endif
if (!(skyeye_cachetype == INSTCACHE))
fault = GetWord (state, address, &data);
else
fault = LoadInstr (state, address, &data);
if (fault) {
/* dyf add for s3c6410 no instcache temporary 2010.9.17 */
if (!(skyeye_cachetype == INSTCACHE)) {
/* set translation fault on prefetch abort */
state->mmu.fault_statusi = fault & 0xFF;
state->mmu.fault_address = address;
}
/* add end */
ARMul_PREFETCHABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Instruction, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize)
{
state->NumScycles++;
#ifdef HOURGLASS
if ((state->NumScycles & HOURGLASS_RATE) == 0) {
HOURGLASS;
}
#endif
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Load Instruction, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize)
{
state->NumNcycles++;
return ARMul_ReLoadInstr (state, address, isize);
}
/***************************************************************************\
* Read Word (but don't tell anyone!) *
\***************************************************************************/
ARMword
ARMul_ReadWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = GetWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Word, Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordS (ARMul_State * state, ARMword address)
{
state->NumScycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Word, Non Sequential Cycle *
\***************************************************************************/
ARMword
ARMul_LoadWordN (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadWord (state, address);
}
/***************************************************************************\
* Load Halfword, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadHalfWord (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
state->NumNcycles++;
fault = GetHalfWord (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Read Byte (but don't tell anyone!) *
\***************************************************************************/
int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
*presult=-1; fault=ALIGNMENT_FAULT; return fault;
}else{
*(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault;
}
}
ARMword
ARMul_ReadByte (ARMul_State * state, ARMword address)
{
ARMword data;
fault_t fault;
fault = GetByte (state, address, &data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return ARMul_ABORTWORD;
}
else {
ARMul_CLEARABORT;
}
return data;
}
/***************************************************************************\
* Load Byte, (Non Sequential Cycle) *
\***************************************************************************/
ARMword
ARMul_LoadByte (ARMul_State * state, ARMword address)
{
state->NumNcycles++;
return ARMul_ReadByte (state, address);
}
/***************************************************************************\
* Write Word (but don't tell anyone!) *
\***************************************************************************/
void
ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
#ifdef ABORTS
if (address >= LOWABORT && address < HIGHABORT) {
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
#endif
fault = PutWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
/***************************************************************************\
* Store Word, Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data)
{
state->NumScycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store Word, Non Sequential Cycle *
\***************************************************************************/
void
ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
ARMul_WriteWord (state, address, data);
}
/***************************************************************************\
* Store HalfWord, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
state->NumNcycles++;
fault = PutHalfWord (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
//chy 2006-04-15
int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault)
return 1;
else
return 0;
}
/***************************************************************************\
* Write Byte (but don't tell anyone!) *
\***************************************************************************/
//chy 2003-07-10, add real write byte fun
void
ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data)
{
fault_t fault;
fault = PutByte (state, address, data);
if (fault) {
state->mmu.fault_status =
(fault | (state->mmu.last_domain << 4)) & 0xFF;
state->mmu.fault_address = address;
ARMul_DATAABORT (address);
return;
}
else {
ARMul_CLEARABORT;
}
}
/***************************************************************************\
* Store Byte, (Non Sequential Cycle) *
\***************************************************************************/
void
ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data)
{
state->NumNcycles++;
#ifdef VALIDATE
if (address == TUBE) {
if (data == 4)
state->Emulate = FALSE;
else
(void) putc ((char) data, stderr); /* Write Char */
return;
}
#endif
ARMul_WriteByte (state, address, data);
}
/***************************************************************************\
* Swap Word, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword
ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
state->NumNcycles++;
temp = ARMul_ReadWord (state, address);
state->NumNcycles++;
PutWord (state, address, data);
return temp;
}
/***************************************************************************\
* Swap Byte, (Two Non Sequential Cycles) *
\***************************************************************************/
ARMword
ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data)
{
ARMword temp;
temp = ARMul_LoadByte (state, address);
ARMul_StoreByte (state, address, data);
return temp;
}
/***************************************************************************\
* Count I Cycles *
\***************************************************************************/
void
ARMul_Icycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumIcycles += number;
ARMul_CLEARABORT;
}
/***************************************************************************\
* Count C Cycles *
\***************************************************************************/
void
ARMul_Ccycles (ARMul_State * state, unsigned number,
ARMword address)
{
state->NumCcycles += number;
ARMul_CLEARABORT;
}