Files
fail/simulators/ovp/armmModel/armmSemiHost.c

183 lines
5.0 KiB
C

/*
* Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com
*
* YOUR ACCESS TO THE INFORMATION IN THIS MODEL IS CONDITIONAL
* UPON YOUR ACCEPTANCE THAT YOU WILL NOT USE OR PERMIT OTHERS
* TO USE THE INFORMATION FOR THE PURPOSES OF DETERMINING WHETHER
* IMPLEMENTATIONS OF THE ARM ARCHITECTURE INFRINGE ANY THIRD
* PARTY PATENTS.
*
* THE LICENSE BELOW EXTENDS ONLY TO USE OF THE SOFTWARE FOR
* MODELING PURPOSES AND SHALL NOT BE CONSTRUED AS GRANTING
* A LICENSE TO CREATE A HARDWARE IMPLEMENTATION OF THE
* FUNCTIONALITY OF THE SOFTWARE LICENSED HEREUNDER.
* YOU MAY USE THE SOFTWARE SUBJECT TO THE LICENSE TERMS BELOW
* PROVIDED THAT YOU ENSURE THAT THIS NOTICE IS REPLICATED UNMODIFIED
* AND IN ITS ENTIRETY IN ALL DISTRIBUTIONS OF THE SOFTWARE,
* MODIFIED OR UNMODIFIED, IN SOURCE CODE OR IN BINARY FORM.
*
* Licensed under an Imperas Modfied 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.ovpworld.org/licenses/OVP_MODIFIED_1.0_APACHE_OPEN_SOURCE_LICENSE_2.0.pdf
*
* 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.
*
*/
// VMI header files
#include "vmi/vmiTypes.h"
#include "vmi/vmiMessage.h"
#include "vmi/vmiMt.h"
// model header files
#include "armFunctions.h"
#include "armRegisters.h"
#include "armStructure.h"
//
// Prefix for messages from this module
//
#define CPU_PREFIX "ARM_SEMIHOST"
//
// Return processor endianness
//
inline static memEndian getEndian(armP arm) {
return armGetEndian((vmiProcessorP)arm, False);
}
//
// Morph return from an opaque intercepted function
//
VMI_INT_RETURN_FN(armIntReturnCB) {
vmimtUncondJumpReg(0, ARM_REG(ARM_REG_LR), VMI_NOREG, vmi_JH_RETURN);
}
//
// This callback should create code to assign function result to the standard
// return result register
//
VMI_INT_RESULT_FN(armIntResultCB) {
vmimtMoveRR(32, ARM_REG(0), VMI_FUNCRESULT);
}
//
// This callback should create code to push 32-bit function parameter 'paramNum'
//
static Uns32 push4ByteArg(vmiProcessorP processor, Uns32 paramNum) {
if(paramNum<=3) {
// argument in a register
vmimtArgReg(32, ARM_REG(paramNum));
} else {
// argument on the stack
armP arm = (armP)processor;
// fetch into a temporary
vmimtLoadRRO(
32, // destBits
32, // memBits
(paramNum-4)*4, // offset
ARM_TEMP(0), // destination (rd)
ARM_REG(ARM_REG_SP), // stack address (ra)
getEndian(arm), // endian
False, // signExtend
False // checkAlign
);
// push temporary argument
vmimtArgReg(32, ARM_TEMP(0));
}
return paramNum+1;
}
//
// This callback should create code to push 64-bit function parameter 'paramNum'
//
static Uns32 push8ByteArg(vmiProcessorP processor, Uns32 paramNum) {
paramNum += push4ByteArg(processor, paramNum);
paramNum += push4ByteArg(processor, paramNum);
return paramNum;
}
//
// This callback should create code to push address function parameter 'paramNum'
//
static Uns32 pushAddressArg(vmiProcessorP processor, Uns32 paramNum) {
if(paramNum<=3) {
// argument in a register
vmimtArgRegSimAddress(32, ARM_REG(paramNum));
} else {
// argument on the stack
armP arm = (armP)processor;
// fetch into a temporary
vmimtLoadRRO(
32, // destBits
32, // memBits
(paramNum-4)*4, // offset
ARM_TEMP(0), // destination (rd)
ARM_REG(ARM_REG_SP), // stack address (ra)
getEndian(arm), // endian
False, // signExtend
False // checkAlign
);
// push temporary argument
vmimtArgRegSimAddress(32, ARM_TEMP(0));
}
return paramNum+1;
}
//
// This callback should create code to push function arguments prior to an
// Imperas standard intercept
//
VMI_INT_PAR_FN(armIntParCB) {
Uns32 paramNum = 0;
char ch;
while((ch=*format++)) {
switch(ch) {
case '4':
paramNum = push4ByteArg(processor, paramNum);
break;
case '8':
paramNum = push8ByteArg(processor, paramNum);
break;
case 'a':
paramNum = pushAddressArg(processor, paramNum);
break;
default:
VMI_ABORT("Unrecognised format character '%c'", ch);
}
}
}