Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
15
simulators/ovp/cortexM3/CMakeLists.txt
Normal file
15
simulators/ovp/cortexM3/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
add_definitions(" -m32 ${IMPERAS_VMIINC} ")
|
||||
|
||||
set(SRCS
|
||||
$ENV{IMPERAS_HOME}/ImpPublic/source/host/icm/icmCpuManager.cpp
|
||||
platform/platform.cc
|
||||
../OVPPlatform.cc
|
||||
)
|
||||
|
||||
add_executable(ovp_cortexM3 ${SRCS})
|
||||
add_dependencies(ovp_cortexM3 ovpstatusmessages )
|
||||
|
||||
|
||||
target_link_libraries(ovp_cortexM3 ${SIM_LDFLAGS} sal cpn comm efw util ovpstatusmessages)
|
||||
## OVP links all needed shared libraries via a runtimeloader
|
||||
set_target_properties(ovp_cortexM3 PROPERTIES LINK_FLAGS "-L${CMAKE_BINARY_DIR}/lib -lpcl -lprotobuf -m32 ")
|
||||
415
simulators/ovp/cortexM3/platform/platform.cc
Normal file
415
simulators/ovp/cortexM3/platform/platform.cc
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "statreg.hpp"
|
||||
#include "sal/SALInst.hpp"
|
||||
|
||||
#include "icm/icmCpuManager.h"
|
||||
#include "icm/icmQuery.h"
|
||||
|
||||
// enable relaxed scheduling for maximum performance
|
||||
//#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED|ICM_ATTR_TRACE)
|
||||
#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED)
|
||||
|
||||
// GDB port
|
||||
#define GDB_PORT 1234
|
||||
|
||||
// Variables set by arguments
|
||||
const char *variant = "Cortex-M3"; // the model variant
|
||||
|
||||
using namespace std;
|
||||
|
||||
ARM_Cortex_M3 arm;
|
||||
|
||||
ARM_Cortex_M3::ARM_Cortex_M3() {
|
||||
}
|
||||
|
||||
ARM_Cortex_M3::~ARM_Cortex_M3() {
|
||||
delete platform;
|
||||
delete cpu;
|
||||
delete attrList;
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::init(bool gdb=false) {
|
||||
|
||||
// initialize OVPsim, enabling verbose mode to get statistics at end of execution
|
||||
platform = new icmPlatform("CortexM3Platform", //name
|
||||
ICM_VERBOSE|ICM_STOP_ON_CTRLC, //attributes
|
||||
gdb ? "rsp" : 0, // optional protocol
|
||||
gdb ? GDB_PORT : 0); // optional port number
|
||||
|
||||
|
||||
// const char *armModel = icmGetVlnvString(NULL, "arm.ovpworld.org", "processor", "armm", "1.0", "model");
|
||||
const char *armModel = "/srv/scratch/hoffmann/test/build/lib/libarmmModel.so";
|
||||
const char *armSemihost = icmGetVlnvString(NULL, "arm.ovpworld.org", "semihosting", "armNewlib", "1.0", "model");
|
||||
|
||||
attrList = new icmAttrListObject();
|
||||
|
||||
attrList->addAttr("endian", "little");
|
||||
attrList->addAttr("compatibility", "nopBKPT");
|
||||
attrList->addAttr("variant", variant);
|
||||
attrList->addAttr("UAL", "1");
|
||||
attrList->addAttr("fail_salp", &fail::simulator);
|
||||
|
||||
char cpuname[64];
|
||||
sprintf(cpuname,"cpu-%s", variant);
|
||||
|
||||
// create a processor instance
|
||||
cpu = new icmProcessorObject(
|
||||
cpuname, // CPU name
|
||||
"armm", // CPU type
|
||||
0, // CPU cpuId
|
||||
0, // CPU model flags
|
||||
32, // address bits
|
||||
armModel, // model file
|
||||
"modelAttrs", // morpher attributes
|
||||
SIM_ATTRS, // attributes
|
||||
attrList, // user-defined attributes
|
||||
armSemihost, // semi-hosting file
|
||||
"modelAttrs" // semi-hosting attributes
|
||||
);
|
||||
|
||||
// Nominate this processor to be attached to a debugger
|
||||
if(gdb) cpu->debugThisProcessor();
|
||||
|
||||
processorP = cpu->getProcessorP();
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::createFullMMC(const char *vlnRoot=0) {
|
||||
// TODO: ELF Groesse auslesen per OVP (hat funktionen) und dann den Bereich als MMC einrichten...
|
||||
/* const char *mmc_model = icmGetVlnvString("/srv/scratch/sirozipp/build/lib", "ovpworld.org", "mmc", "failMMC", "1.0", "model");
|
||||
if(mmc_model == NULL) {
|
||||
std::cerr << "mmc_model not found!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
const char *mmc_model = "/srv/scratch/sirozipp/build/lib/libflaky.so";
|
||||
|
||||
// create full MMCs
|
||||
mmcInstr = new icmMmcObject("mmci", mmc_model, "modelAttrs", 0, False);
|
||||
mmcData = new icmMmcObject("mmcd", mmc_model, "modelAttrs", 0, False);
|
||||
|
||||
// create processor instruction and data bus
|
||||
instrBus = new icmBusObject("instrbus", 32);
|
||||
dataBus = new icmBusObject("databus", 32);
|
||||
|
||||
// create processor main bus
|
||||
mainBus = new icmBusObject("mainbus", 32);
|
||||
|
||||
// connect processor ports to their buses
|
||||
cpu->connect(*instrBus, *dataBus);
|
||||
|
||||
// connect mmcs to buses
|
||||
mmcInstr->connect(*instrBus, "sp1", False);
|
||||
mmcData->connect(*dataBus, "sp1", False);
|
||||
|
||||
// connet master ports of mmc to main bus
|
||||
mmcInstr->connect(*mainBus, "mp1", True);
|
||||
mmcData->connect(*mainBus, "mp1", True);
|
||||
|
||||
// create simulated memory
|
||||
Addr appHighAddr, appLowAddr;
|
||||
|
||||
appHighAddr = 0xFFFFFFFF;
|
||||
appLowAddr = 0x0;
|
||||
icmMem0 = new icmMemoryObject("mem1", ICM_PRIV_RWX, appHighAddr-appLowAddr);
|
||||
|
||||
// connect memory to main bus
|
||||
icmMem0->connect("mp1", *mainBus, 0);
|
||||
}
|
||||
|
||||
static ICM_MEM_READ_FN(extMemRead) {
|
||||
unsigned char res[4];
|
||||
// Int32 tmpres = *(Int32*)value;
|
||||
// icmPrintf("EXTERNAL MEMORY: Reading 0x%08x from 0x%08x\n", *(Int32*)value, (Int32)address);
|
||||
// *(Int32*) value = (Int32)arm.mem[(address-arm.offset)>>2];
|
||||
|
||||
fail::simulator.onMemoryAccessEvent(address, 4, false, ovpplatform.getPC());
|
||||
|
||||
res[0] = arm.mem[(address-arm.offset)+0];
|
||||
res[1] = arm.mem[(address-arm.offset)+1];
|
||||
res[2] = arm.mem[(address-arm.offset)+2];
|
||||
res[3] = arm.mem[(address-arm.offset)+3];
|
||||
|
||||
// icmPrintf("Reading [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]);
|
||||
|
||||
*(Int32*)value = (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0];
|
||||
//
|
||||
// icmPrintf("Reading: 0x%08x\n", (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0]);
|
||||
|
||||
// icmPrintf("Callback: Reading 0x%08x from mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), tmpres, (Int32) address);
|
||||
|
||||
}
|
||||
|
||||
static ICM_MEM_WRITE_FN(extMemWrite) {
|
||||
// icmPrintf("EXTERNAL MEMORY: Writing 0x%08x to 0x%08x\n", (Int32)value, (Int32)address);
|
||||
// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address);
|
||||
fail::simulator.onMemoryAccessEvent(address, 4, true, ovpplatform.getPC());
|
||||
|
||||
Int32 val = *(Int32*)value;
|
||||
|
||||
arm.mem[(address-arm.offset) + 0] = val & 0xFF;
|
||||
arm.mem[(address-arm.offset) + 1] = (val >> 8) & 0xFF;
|
||||
arm.mem[(address-arm.offset) + 2] = (val >> 16) & 0xFF;
|
||||
arm.mem[(address-arm.offset) + 3] = (val >> 24) & 0xFF;
|
||||
|
||||
// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF);
|
||||
// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]);
|
||||
|
||||
// Int32 res = arm.mem[(address-arm.offset)+0] | arm.mem[(address-arm.offset)+1] << 8 | arm.mem[(address-arm.offset)+2] << 16 | arm.mem[(address-arm.offset)+3] << 24;
|
||||
|
||||
// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x to [0x%08x]\n", res, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address);
|
||||
// arm.mem[(address-arm.offset) >> 2] = *(Int32*) value;
|
||||
}
|
||||
|
||||
static ICM_MEM_READ_FN(extTextRead) {
|
||||
// Int16 val = *(Int16*)value;
|
||||
*(Int16*) value = (Int16)arm.textmem[(address-arm.textOffset)>>1];
|
||||
// icmPrintf("Callback: Reading 0x%04x from textmem[0x%08x] should be 0x%04x from [0x%08x]\n", *(Int16*)value, (Int32)(address-arm.textOffset), val, (Int32) address);
|
||||
}
|
||||
|
||||
static ICM_MEM_WRITE_FN(extTextWrite) {
|
||||
arm.textmem[(address-arm.textOffset) >> 1] = *(Int16*) value;
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::mapMemToCallback() {
|
||||
// create processor bus
|
||||
mainBus = new icmBusObject("mainbus", 32);
|
||||
|
||||
// connect the processor bus
|
||||
cpu->connect(*mainBus, *mainBus);
|
||||
|
||||
// create simulated memory
|
||||
Addr appHighAddr, appLowAddr, textLowAddr, textHighAddr, LowAddr, LowAddrH, HighAddr, HighAddrL;
|
||||
|
||||
appLowAddr = offset;
|
||||
appHighAddr = appLowAddr + memSize - 1;
|
||||
|
||||
textLowAddr = textOffset;
|
||||
textHighAddr = textLowAddr + textMemSize - 1;
|
||||
|
||||
// check which section is first
|
||||
if(appLowAddr < textLowAddr) {
|
||||
LowAddr = appLowAddr;
|
||||
LowAddrH = appHighAddr;
|
||||
HighAddr = textHighAddr;
|
||||
HighAddrL = textLowAddr;
|
||||
} else {
|
||||
LowAddr = textLowAddr;
|
||||
LowAddrH = textHighAddr;
|
||||
HighAddr = appHighAddr;
|
||||
HighAddrL = appLowAddr;
|
||||
}
|
||||
|
||||
// Memory from 0x0 to LowAddr
|
||||
icmMem0 = new icmMemoryObject("mem0", ICM_PRIV_RWX, LowAddr - 1);
|
||||
// Memory after callback mem to end
|
||||
icmMem1 = new icmMemoryObject("mem1", ICM_PRIV_RWX, 0xFFFFFFFF - HighAddr - 1);
|
||||
// Memory between text and other sections
|
||||
icmMem2 = new icmMemoryObject("mem2", ICM_PRIV_RWX, HighAddrL - LowAddrH - 1 -1);
|
||||
|
||||
// map the adress range appLowAddr:appHighAddr externally to the processor
|
||||
mainBus->mapExternalMemory("external", ICM_PRIV_RWX, appLowAddr, appHighAddr,
|
||||
extMemRead, // read callback
|
||||
extMemWrite, // write callback
|
||||
0);
|
||||
|
||||
mainBus->mapExternalMemory("exttext", ICM_PRIV_RWX, textLowAddr, textHighAddr,
|
||||
extTextRead,
|
||||
extTextWrite,
|
||||
0);
|
||||
|
||||
// just build memory before external memory if it's not at the beginning
|
||||
if(LowAddr > 0x0) {
|
||||
icmMem0->connect("mp1", *mainBus, 0x0);
|
||||
}
|
||||
|
||||
if(HighAddr < 0xffffffff) {
|
||||
icmMem1->connect("mp2", *mainBus, HighAddr+1);
|
||||
}
|
||||
|
||||
if(LowAddrH != HighAddrL) {
|
||||
icmMem2->connect("mp3", *mainBus, LowAddrH+1);
|
||||
}
|
||||
|
||||
mainBus->printConnections();
|
||||
}
|
||||
|
||||
|
||||
void ARM_Cortex_M3::makeGPRegister() {
|
||||
const string names[] = {"r0", "r1", "r2", "r3", "r4", "r5",
|
||||
"r6", "r7", "r8", "r9", "r10", "r11", "r12"};
|
||||
|
||||
|
||||
|
||||
for(int i = 0; i <= 12; ++i) {
|
||||
icmRegInfoP reg = icmGetRegByIndex(processorP, i);
|
||||
fail::simulator.makeGPRegister(32, (void *)reg, names[i]);
|
||||
}
|
||||
|
||||
// set SP pointer
|
||||
// ARM Cortex M3: SP pointer is ID 13
|
||||
icmRegInfoP sp_reg = icmGetRegByIndex(processorP, 13);
|
||||
setSPReg(sp_reg);
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::makeSTRegister() {
|
||||
OVPStatusRegister *streg = new CortexM3StatusRegister();
|
||||
|
||||
fail::simulator.makeSTRegister(streg, "sp");
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::makePCRegister() {
|
||||
// ARM Cortex M3: PC pointer is ID 15
|
||||
icmRegInfoP pc_reg = icmGetRegByIndex(processorP, 15);
|
||||
fail::simulator.makePCRegister(32, (void *)pc_reg, "PC");
|
||||
}
|
||||
|
||||
int ARM_Cortex_M3::startSimulation(const char *app) {
|
||||
bool loadPhysical = true;
|
||||
bool verbose = true;
|
||||
bool useEntry = true;
|
||||
if(!cpu->loadLocalMemory(app, loadPhysical, verbose, useEntry))
|
||||
return -1;
|
||||
|
||||
// application is loaded, now fill the callback memory with program data
|
||||
fillCallbackMemory();
|
||||
|
||||
// icmSimulatePlatform();
|
||||
|
||||
while(1) {
|
||||
// save PC
|
||||
Addr pc_ptr = cpu->getPC();
|
||||
|
||||
fail::simulator.onInstrPtrChanged(pc_ptr);
|
||||
|
||||
// simulate the platform
|
||||
icmStopReason stopreason = cpu->simulate(1);
|
||||
|
||||
if(stopreason!=0x00) {
|
||||
// was simulation interrupted or did it complete
|
||||
if(stopreason==ICM_SR_INTERRUPT) {
|
||||
icmPrintf("*** simulation interrupted\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
//icmTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::makeCallbackMemory(size_t sizeText, size_t offText, size_t sizeMem, size_t offMem) {
|
||||
mem = new unsigned char[sizeMem];
|
||||
//mem = new Int32[sizeMem>>2];
|
||||
textmem = new Int16[sizeText>>1];
|
||||
offset = offMem;
|
||||
textOffset = offText;
|
||||
memSize = sizeMem;
|
||||
textMemSize = sizeText;
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::save(const string& path) {
|
||||
OVPStatusMessage ovpstat;
|
||||
|
||||
// save registers
|
||||
// FIXME: what about reg with id 16? should be status register
|
||||
for(unsigned int i = 0; i < 16; ++i) {
|
||||
uint32_t tmp = 0;
|
||||
icmRegInfoP reg = icmGetRegByIndex(processorP, i);
|
||||
icmReadRegInfoValue(processorP, reg, (void *)&tmp);
|
||||
OVPStatusMessage::Register *msgReg = ovpstat.add_reg();
|
||||
|
||||
switch(i) {
|
||||
case 13: msgReg->set_name("sp");
|
||||
break;
|
||||
case 14: msgReg->set_name("lr");
|
||||
break;
|
||||
case 15: msgReg->set_name("pc");
|
||||
break;
|
||||
case 16: msgReg->set_name("sr");
|
||||
break;
|
||||
default: char num[3];
|
||||
sprintf(num, "r%d", i);
|
||||
msgReg->set_name(num);
|
||||
}
|
||||
|
||||
msgReg->set_value(tmp);
|
||||
// std::cerr << "save " << i << ": " << tmp << std::endl;
|
||||
}
|
||||
|
||||
|
||||
string stmp;
|
||||
ovpstat.SerializeToString(&stmp);
|
||||
ofstream file;
|
||||
file.open(path.c_str(), ios::out);
|
||||
file << stmp;
|
||||
file.close();
|
||||
/* ofstream file(path.c_str(), ios::out | ios::trunc);
|
||||
if(!ovpstat.SerializeToOstream(&file)) {
|
||||
std::cerr << "Error writing to file " << path << "!" << std::endl;
|
||||
}*/
|
||||
}
|
||||
|
||||
void ARM_Cortex_M3::restore(const string& path) {
|
||||
fstream input(path.c_str(), ios::in);
|
||||
OVPStatusMessage ovpstat;
|
||||
ovpstat.ParseFromIstream(&input);
|
||||
|
||||
for(int i = 0; i < ovpstat.reg_size(); ++i) {
|
||||
const OVPStatusMessage::Register& ovpreg = ovpstat.reg(i);
|
||||
uint32_t val = ovpreg.value();
|
||||
// std::cerr << "restore "<<ovpreg.name()<<": " << val << std::endl;
|
||||
icmRegInfoP reg = icmGetRegByIndex(processorP, i);
|
||||
icmWriteRegInfoValue(processorP, reg, (void *)&val);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if(argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " application" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
arm.init(false);
|
||||
|
||||
// arm.createFullMMC();
|
||||
|
||||
// arm.makeCallbackMemory(0x100, 0x20000000);
|
||||
// arm.makeCallbackMemory(0x8034, 0x0, 0x11c, 0x82e8);
|
||||
// arm.makeCallbackMemory(0x8034, 0x0, 0x940, 0x8040);
|
||||
arm.makeCallbackMemory(0x802c, 0x0, 0x930, 0x8038);
|
||||
arm.mapMemToCallback();
|
||||
|
||||
|
||||
ovpplatform.setCpu((void *) &arm);
|
||||
|
||||
arm.makeGPRegister();
|
||||
arm.makeSTRegister();
|
||||
arm.makePCRegister();
|
||||
|
||||
arm.startSimulation(argv[1]);
|
||||
}
|
||||
36
simulators/ovp/cortexM3/platform/platform.hpp
Normal file
36
simulators/ovp/cortexM3/platform/platform.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef _armCortexM3_HPP_
|
||||
#define _armCortexM3_HPP_
|
||||
|
||||
|
||||
#include "../../OVPCpu.hpp"
|
||||
#include "ovp/statusmsg/OVPStatusMessage.pb.h"
|
||||
|
||||
using namespace icmCpuManager;
|
||||
|
||||
/**
|
||||
* \class ARM_Cortex_M3
|
||||
* Implements the OVP platform for ARM Cortex M3 with callback memory
|
||||
*/
|
||||
class ARM_Cortex_M3 : public OVPCpu {
|
||||
private:
|
||||
|
||||
public:
|
||||
ARM_Cortex_M3();
|
||||
~ARM_Cortex_M3();
|
||||
void init(bool);
|
||||
int startSimulation(const char*);
|
||||
void createFullMMC(const char *);
|
||||
void mapMemToCallback();
|
||||
|
||||
void makeGPRegister();
|
||||
void makeSTRegister();
|
||||
void makePCRegister();
|
||||
|
||||
void makeCallbackMemory(size_t, size_t, size_t, size_t);
|
||||
|
||||
void save(const string&);
|
||||
void restore(const string&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
92
simulators/ovp/cortexM3/platform/statreg.hpp
Normal file
92
simulators/ovp/cortexM3/platform/statreg.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "platform.hpp"
|
||||
#include "../../OVPStatusRegister.hpp"
|
||||
|
||||
extern ARM_Cortex_M3 arm;
|
||||
|
||||
/**
|
||||
* \class CortexM3StatusRegister
|
||||
* Status register for ARM Cortex M3
|
||||
*/
|
||||
class CortexM3StatusRegister : public OVPStatusRegister {
|
||||
|
||||
private:
|
||||
icmRegInfoP cpsr; //!< pointer to status register
|
||||
icmProcessorP cpuP;
|
||||
|
||||
public:
|
||||
CortexM3StatusRegister() : OVPStatusRegister(32, icmGetRegByIndex(arm.getProcessorP(), 16)) {
|
||||
cpuP = arm.getProcessorP();
|
||||
|
||||
// status register is index 16
|
||||
cpsr = icmGetRegByIndex(cpuP, 16);
|
||||
}
|
||||
|
||||
~CortexM3StatusRegister() {}
|
||||
|
||||
bool getFlag(int pos) const {
|
||||
uint32_t val;
|
||||
uint32_t bit;
|
||||
icmReadRegInfoValue(cpuP, cpsr, (void *)&val);
|
||||
|
||||
// put bit to correct place
|
||||
bit = 1 << pos;
|
||||
|
||||
// Flag at position pos
|
||||
val = val & bit;
|
||||
val = val >> pos;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void setFlag(int pos, bool newval) {
|
||||
uint32_t val;
|
||||
uint32_t bit = 1 << pos;
|
||||
|
||||
icmReadRegInfoValue(cpuP, cpsr, (void *)&val);
|
||||
|
||||
if(newval == 0) {
|
||||
// AND with 0xFFFEFFFF (e.g.)
|
||||
bit = ~bit; // invert bits
|
||||
|
||||
val = val & bit;
|
||||
} else {
|
||||
// OR with 0x00010000 (e.g.)
|
||||
val = val | bit;
|
||||
}
|
||||
|
||||
icmWriteRegInfoValue(cpuP, cpsr, (void *)&val);
|
||||
}
|
||||
|
||||
bool getSignFlag() const {
|
||||
return getFlag(31);
|
||||
}
|
||||
|
||||
bool getZeroFlag() const {
|
||||
return getFlag(30);
|
||||
}
|
||||
|
||||
bool getCarryFlag() const {
|
||||
return getFlag(29);
|
||||
}
|
||||
|
||||
bool getOverflowFlag() const {
|
||||
return getFlag(28);
|
||||
}
|
||||
|
||||
void setSignFlag(bool b) {
|
||||
setFlag(31, b);
|
||||
}
|
||||
|
||||
void setZeroFlag(bool b) {
|
||||
setFlag(30, b);
|
||||
}
|
||||
|
||||
void setCarryFlag(bool b) {
|
||||
setFlag(29, b);
|
||||
}
|
||||
|
||||
void setOverflowFlag(bool b) {
|
||||
setFlag(28, b);
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user