2016-07-01 14:01:06 +01:00
|
|
|
/* This file is part of the dynarmic project.
|
|
|
|
* Copyright (c) 2016 MerryMage
|
|
|
|
* This software may be used and distributed according to the terms of the GNU
|
|
|
|
* General Public License version 2 or any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2016-07-04 10:22:11 +01:00
|
|
|
#include "frontend/arm_types.h"
|
|
|
|
#include "frontend/ir/ir.h"
|
|
|
|
#include "frontend/ir/opcodes.h"
|
2016-07-01 14:01:06 +01:00
|
|
|
|
|
|
|
namespace Dynarmic {
|
|
|
|
namespace Arm {
|
|
|
|
|
|
|
|
class IREmitter {
|
|
|
|
public:
|
2016-07-04 14:37:50 +01:00
|
|
|
explicit IREmitter(LocationDescriptor descriptor) : block(descriptor), current_location(descriptor) {}
|
|
|
|
|
|
|
|
IR::Block block;
|
|
|
|
LocationDescriptor current_location;
|
2016-07-01 14:01:06 +01:00
|
|
|
|
|
|
|
struct ResultAndCarry {
|
|
|
|
IR::ValuePtr result;
|
|
|
|
IR::ValuePtr carry;
|
|
|
|
};
|
|
|
|
|
2016-07-08 10:09:18 +01:00
|
|
|
struct ResultAndCarryAndOverflow {
|
|
|
|
IR::ValuePtr result;
|
|
|
|
IR::ValuePtr carry;
|
|
|
|
IR::ValuePtr overflow;
|
|
|
|
};
|
|
|
|
|
2016-07-01 14:01:06 +01:00
|
|
|
void Unimplemented();
|
2016-07-11 22:43:53 +01:00
|
|
|
u32 PC();
|
|
|
|
u32 AlignPC(size_t alignment);
|
2016-07-01 14:01:06 +01:00
|
|
|
|
2016-07-08 10:09:18 +01:00
|
|
|
IR::ValuePtr Imm1(bool value);
|
2016-07-01 14:01:06 +01:00
|
|
|
IR::ValuePtr Imm8(u8 value);
|
2016-07-08 10:09:18 +01:00
|
|
|
IR::ValuePtr Imm32(u32 value);
|
2016-07-01 14:01:06 +01:00
|
|
|
|
|
|
|
IR::ValuePtr GetRegister(Reg source_reg);
|
|
|
|
void SetRegister(const Reg dest_reg, IR::ValuePtr value);
|
|
|
|
|
2016-07-08 10:09:18 +01:00
|
|
|
void ALUWritePC(IR::ValuePtr value);
|
2016-07-18 21:04:39 +01:00
|
|
|
void BranchWritePC(IR::ValuePtr value);
|
|
|
|
void BXWritePC(IR::ValuePtr value);
|
2016-07-12 10:58:14 +01:00
|
|
|
void LoadWritePC(IR::ValuePtr value);
|
2016-07-14 14:04:43 +01:00
|
|
|
void CallSupervisor(IR::ValuePtr value);
|
2016-07-08 10:09:18 +01:00
|
|
|
|
2016-07-01 14:01:06 +01:00
|
|
|
IR::ValuePtr GetCFlag();
|
|
|
|
void SetNFlag(IR::ValuePtr value);
|
|
|
|
void SetZFlag(IR::ValuePtr value);
|
|
|
|
void SetCFlag(IR::ValuePtr value);
|
2016-07-08 10:09:18 +01:00
|
|
|
void SetVFlag(IR::ValuePtr value);
|
2016-07-01 14:01:06 +01:00
|
|
|
|
2016-07-11 23:06:35 +01:00
|
|
|
IR::ValuePtr LeastSignificantHalf(IR::ValuePtr value);
|
2016-07-01 14:01:06 +01:00
|
|
|
IR::ValuePtr LeastSignificantByte(IR::ValuePtr value);
|
|
|
|
IR::ValuePtr MostSignificantBit(IR::ValuePtr value);
|
|
|
|
IR::ValuePtr IsZero(IR::ValuePtr value);
|
|
|
|
|
|
|
|
ResultAndCarry LogicalShiftLeft(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
|
|
|
ResultAndCarry LogicalShiftRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
2016-07-04 10:22:11 +01:00
|
|
|
ResultAndCarry ArithmeticShiftRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
2016-07-10 01:18:17 +01:00
|
|
|
ResultAndCarry RotateRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in);
|
2016-07-08 10:09:18 +01:00
|
|
|
ResultAndCarryAndOverflow AddWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
|
2016-07-11 22:43:53 +01:00
|
|
|
IR::ValuePtr Add(IR::ValuePtr a, IR::ValuePtr b);
|
2016-07-08 11:49:30 +01:00
|
|
|
ResultAndCarryAndOverflow SubWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
|
2016-07-18 15:11:16 +01:00
|
|
|
IR::ValuePtr Sub(IR::ValuePtr a, IR::ValuePtr b);
|
2016-07-08 10:43:28 +01:00
|
|
|
IR::ValuePtr And(IR::ValuePtr a, IR::ValuePtr b);
|
2016-07-08 11:14:50 +01:00
|
|
|
IR::ValuePtr Eor(IR::ValuePtr a, IR::ValuePtr b);
|
2016-07-10 02:06:38 +01:00
|
|
|
IR::ValuePtr Or(IR::ValuePtr a, IR::ValuePtr b);
|
2016-07-10 03:44:45 +01:00
|
|
|
IR::ValuePtr Not(IR::ValuePtr a);
|
2016-07-16 19:23:42 +01:00
|
|
|
IR::ValuePtr SignExtendHalfToWord(IR::ValuePtr a);
|
|
|
|
IR::ValuePtr SignExtendByteToWord(IR::ValuePtr a);
|
|
|
|
IR::ValuePtr ZeroExtendHalfToWord(IR::ValuePtr a);
|
|
|
|
IR::ValuePtr ZeroExtendByteToWord(IR::ValuePtr a);
|
|
|
|
IR::ValuePtr ByteReverseWord(IR::ValuePtr a);
|
|
|
|
IR::ValuePtr ByteReverseHalf(IR::ValuePtr a);
|
2016-07-01 14:01:06 +01:00
|
|
|
|
2016-07-11 22:43:53 +01:00
|
|
|
IR::ValuePtr ReadMemory8(IR::ValuePtr vaddr);
|
|
|
|
IR::ValuePtr ReadMemory16(IR::ValuePtr vaddr);
|
|
|
|
IR::ValuePtr ReadMemory32(IR::ValuePtr vaddr);
|
|
|
|
IR::ValuePtr ReadMemory64(IR::ValuePtr vaddr);
|
|
|
|
void WriteMemory8(IR::ValuePtr vaddr, IR::ValuePtr value);
|
|
|
|
void WriteMemory16(IR::ValuePtr vaddr, IR::ValuePtr value);
|
|
|
|
void WriteMemory32(IR::ValuePtr vaddr, IR::ValuePtr value);
|
|
|
|
void WriteMemory64(IR::ValuePtr vaddr, IR::ValuePtr value);
|
|
|
|
|
2016-07-07 10:53:09 +01:00
|
|
|
void SetTerm(const IR::Terminal& terminal);
|
|
|
|
|
2016-07-01 14:01:06 +01:00
|
|
|
private:
|
|
|
|
IR::ValuePtr Inst(IR::Opcode op, std::initializer_list<IR::ValuePtr> args);
|
|
|
|
IR::ValuePtr RegRef(Reg reg);
|
|
|
|
void AddToBlock(IR::ValuePtr value);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Arm
|
|
|
|
} // namespace Dynarmic
|