XADMaster/RARVirtualMachine.h
2018-03-21 14:24:50 +02:00

189 lines
5.9 KiB
C

/*
* RARVirtualMachine.h
*
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RARVIRTUALMACHINE_H__
#define __RARVIRTUALMACHINE_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
#define RARProgramMemorySize 0x40000
#define RARProgramMemoryMask (RARProgramMemorySize-1)
#define RARProgramWorkSize 0x3c000
#define RARProgramGlobalSize 0x2000
#define RARProgramSystemGlobalAddress RARProgramWorkSize
#define RARProgramSystemGlobalSize 64
#define RARProgramUserGlobalAddress (RARProgramSystemGlobalAddress+RARProgramSystemGlobalSize)
#define RARProgramUserGlobalSize (RARProgramGlobalSize-RARProgramSystemGlobalSize)
typedef struct RARVirtualMachine
{
uint32_t registers[8];
uint32_t flags;
// TODO: align?
uint8_t memory[RARProgramMemorySize+3]; // Let memory accesses at the end overflow.
// Possibly not 100% correct but unlikely to be a problem.
} RARVirtualMachine;
typedef uint32_t (*RARGetterFunction)(RARVirtualMachine *self,uint32_t value);
typedef void (*RARSetterFunction)(RARVirtualMachine *self,uint32_t value,uint32_t data);
typedef struct RAROpcode
{
void *instructionlabel;
RARGetterFunction operand1getter;
RARSetterFunction operand1setter;
uint32_t value1;
RARGetterFunction operand2getter;
RARSetterFunction operand2setter;
uint32_t value2;
uint8_t instruction;
uint8_t bytemode;
uint8_t addressingmode1;
uint8_t addressingmode2;
#if UINTPTR_MAX==UINT64_MAX
uint8_t padding[12]; // 64-bit machine, pad to 64 bytes
#endif
} RAROpcode;
// Setup
void InitializeRARVirtualMachine(RARVirtualMachine *self);
// Program building
void SetRAROpcodeInstruction(RAROpcode *opcode,unsigned int instruction,bool bytemode);
void SetRAROpcodeOperand1(RAROpcode *opcode,unsigned int addressingmode,uint32_t value);
void SetRAROpcodeOperand2(RAROpcode *opcode,unsigned int addressingmode,uint32_t value);
bool IsProgramTerminated(RAROpcode *opcodes,int numopcodes);
bool PrepareRAROpcodes(RAROpcode *opcodes,int numopcodes);
// Execution
bool ExecuteRARCode(RARVirtualMachine *self,RAROpcode *opcodes,int numopcodes);
// Instruction properties
int NumberOfRARInstructionOperands(unsigned int instruction);
bool RARInstructionHasByteMode(unsigned int instruction);
bool RARInstructionIsUnconditionalJump(unsigned int instruction);
bool RARInstructionIsRelativeJump(unsigned int instruction);
bool RARInstructionWritesFirstOperand(unsigned int instruction);
bool RARInstructionWritesSecondOperand(unsigned int instruction);
// Disassembling
char *DescribeRAROpcode(RAROpcode *opcode);
char *DescribeRARInstruction(RAROpcode *opcode);
char *DescribeRAROperand1(RAROpcode *opcode);
char *DescribeRAROperand2(RAROpcode *opcode);
static inline void SetRARVirtualMachineRegisters(RARVirtualMachine *self,uint32_t registers[8])
{
memcpy(self->registers,registers,sizeof(self->registers));
}
static inline uint32_t _RARRead32(const uint8_t *b) { return ((uint32_t)b[3]<<24)|((uint32_t)b[2]<<16)|((uint32_t)b[1]<<8)|(uint32_t)b[0]; }
static inline void _RARWrite32(uint8_t *b,uint32_t n) { b[3]=(n>>24)&0xff; b[2]=(n>>16)&0xff; b[1]=(n>>8)&0xff; b[0]=n&0xff; }
static inline uint32_t RARVirtualMachineRead32(RARVirtualMachine *self,uint32_t address)
{
return _RARRead32(&self->memory[address&RARProgramMemoryMask]);
}
static inline void RARVirtualMachineWrite32(RARVirtualMachine *self,uint32_t address,uint32_t val)
{
_RARWrite32(&self->memory[address&RARProgramMemoryMask],val);
}
static inline uint32_t RARVirtualMachineRead8(RARVirtualMachine *self,uint32_t address)
{
return self->memory[address&RARProgramMemoryMask];
}
static inline void RARVirtualMachineWrite8(RARVirtualMachine *self,uint32_t address,uint32_t val)
{
self->memory[address&RARProgramMemoryMask]=val;
}
#define RARMovInstruction 0
#define RARCmpInstruction 1
#define RARAddInstruction 2
#define RARSubInstruction 3
#define RARJzInstruction 4
#define RARJnzInstruction 5
#define RARIncInstruction 6
#define RARDecInstruction 7
#define RARJmpInstruction 8
#define RARXorInstruction 9
#define RARAndInstruction 10
#define RAROrInstruction 11
#define RARTestInstruction 12
#define RARJsInstruction 13
#define RARJnsInstruction 14
#define RARJbInstruction 15
#define RARJbeInstruction 16
#define RARJaInstruction 17
#define RARJaeInstruction 18
#define RARPushInstruction 19
#define RARPopInstruction 20
#define RARCallInstruction 21
#define RARRetInstruction 22
#define RARNotInstruction 23
#define RARShlInstruction 24
#define RARShrInstruction 25
#define RARSarInstruction 26
#define RARNegInstruction 27
#define RARPushaInstruction 28
#define RARPopaInstruction 29
#define RARPushfInstruction 30
#define RARPopfInstruction 31
#define RARMovzxInstruction 32
#define RARMovsxInstruction 33
#define RARXchgInstruction 34
#define RARMulInstruction 35
#define RARDivInstruction 36
#define RARAdcInstruction 37
#define RARSbbInstruction 38
#define RARPrintInstruction 39
#define RARNumberOfInstructions 40
#define RARRegisterAddressingMode(n) (0+(n))
#define RARRegisterIndirectAddressingMode(n) (8+(n))
#define RARIndexedAbsoluteAddressingMode(n) (16+(n))
#define RARAbsoluteAddressingMode 24
#define RARImmediateAddressingMode 25
#define RARNumberOfAddressingModes 26
#endif