update ares
This commit is contained in:
parent
b1207b9c2c
commit
b8444f8bd2
Binary file not shown.
|
@ -146,3 +146,38 @@ If you redistribute modified sources, we would appreciate that you include in
|
|||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
||||
----------------------------------------------------------------------
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2021 Yann Collet
|
||||
|
||||
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at:
|
||||
- xxHash homepage: https://www.xxhash.com
|
||||
- xxHash source repository: https://github.com/Cyan4973/xxHash
|
||||
|
|
|
@ -15,7 +15,7 @@ struct Accuracy {
|
|||
static constexpr bool Recompiler = !Interpreter;
|
||||
|
||||
//VU instructions
|
||||
static constexpr bool SISD = 0;// | Reference | !Architecture::amd64 | !Architecture::sse41;
|
||||
static constexpr bool SISD = 0;// | Reference | !Architecture::sse41;
|
||||
static constexpr bool SIMD = !SISD;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,27 +25,32 @@ auto AI::unload() -> void {
|
|||
}
|
||||
|
||||
auto AI::main() -> void {
|
||||
sample();
|
||||
f64 left = 0, right = 0;
|
||||
sample(left, right);
|
||||
stream->frame(left, right);
|
||||
step(dac.period);
|
||||
}
|
||||
|
||||
auto AI::sample() -> void {
|
||||
if(io.dmaCount == 0) return stream->frame(0.0, 0.0);
|
||||
auto AI::sample(f64& left, f64& right) -> void {
|
||||
if(io.dmaCount == 0) return;
|
||||
|
||||
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
|
||||
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
|
||||
auto left = s16(data >> 16);
|
||||
auto right = s16(data >> 0);
|
||||
stream->frame(left / 32768.0, right / 32768.0);
|
||||
if(io.dmaLength[0] && io.dmaEnable) {
|
||||
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
|
||||
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
|
||||
auto l = s16(data >> 16);
|
||||
auto r = s16(data >> 0);
|
||||
left = l / 32768.0;
|
||||
right = r / 32768.0;
|
||||
|
||||
io.dmaAddress[0].bit(0,12) += 4;
|
||||
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
|
||||
io.dmaLength[0] -= 4;
|
||||
io.dmaAddress[0].bit(0,12) += 4;
|
||||
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
|
||||
io.dmaLength[0] -= 4;
|
||||
}
|
||||
if(!io.dmaLength[0]) {
|
||||
mi.raise(MI::IRQ::AI);
|
||||
if(--io.dmaCount) {
|
||||
io.dmaAddress[0] = io.dmaAddress[1];
|
||||
io.dmaLength [0] = io.dmaLength [1];
|
||||
mi.raise(MI::IRQ::AI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ struct AI : Thread, Memory::IO<AI> {
|
|||
auto load(Node::Object) -> void;
|
||||
auto unload() -> void;
|
||||
auto main() -> void;
|
||||
auto sample() -> void;
|
||||
auto sample(f64& left, f64& right) -> void;
|
||||
auto step(u32 clocks) -> void;
|
||||
auto power(bool reset) -> void;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ auto AI::readWord(u32 address) -> u32 {
|
|||
data.bit( 0) = io.dmaCount > 1;
|
||||
data.bit(20) = 1;
|
||||
data.bit(24) = 1;
|
||||
data.bit(25) = io.dmaEnable;
|
||||
data.bit(30) = io.dmaCount > 0;
|
||||
data.bit(31) = io.dmaCount > 1;
|
||||
}
|
||||
|
@ -34,7 +35,8 @@ auto AI::writeWord(u32 address, u32 data_) -> void {
|
|||
if(address == 1) {
|
||||
//AI_LENGTH
|
||||
n18 length = data.bit(0,17) & ~7;
|
||||
if(io.dmaCount < 2 && length) {
|
||||
if(io.dmaCount < 2) {
|
||||
if(io.dmaCount == 0) mi.raise(MI::IRQ::AI);
|
||||
io.dmaLength[io.dmaCount] = length;
|
||||
io.dmaCount++;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace ares::Nintendo64 {
|
|||
|
||||
CPU cpu;
|
||||
#include "context.cpp"
|
||||
#include "icache.cpp"
|
||||
#include "dcache.cpp"
|
||||
#include "tlb.cpp"
|
||||
#include "memory.cpp"
|
||||
|
|
|
@ -103,26 +103,80 @@ struct CPU : Thread {
|
|||
|
||||
//icache.cpp
|
||||
struct InstructionCache {
|
||||
CPU& self;
|
||||
struct Line;
|
||||
auto line(u32 address) -> Line&;
|
||||
auto step(u32 address) -> void;
|
||||
auto fetch(u32 address) -> u32;
|
||||
auto read(u32 address) -> u32;
|
||||
auto power(bool reset) -> void;
|
||||
auto line(u32 address) -> Line& { return lines[address >> 5 & 0x1ff]; }
|
||||
|
||||
//used by the recompiler to simulate instruction cache fetch timing
|
||||
auto step(u32 address) -> void {
|
||||
auto& line = this->line(address);
|
||||
if(!line.hit(address)) {
|
||||
self.step(48);
|
||||
line.valid = 1;
|
||||
line.tag = address & ~0x0000'0fff;
|
||||
} else {
|
||||
self.step(2);
|
||||
}
|
||||
}
|
||||
|
||||
//used by the interpreter to fully emulate the instruction cache
|
||||
auto fetch(u32 address, CPU& cpu) -> u32 {
|
||||
auto& line = this->line(address);
|
||||
if(!line.hit(address)) {
|
||||
line.fill(address, cpu);
|
||||
} else {
|
||||
cpu.step(2);
|
||||
}
|
||||
return line.read(address);
|
||||
}
|
||||
|
||||
auto power(bool reset) -> void {
|
||||
u32 index = 0;
|
||||
for(auto& line : lines) {
|
||||
line.valid = 0;
|
||||
line.tag = 0;
|
||||
line.index = index++ << 5 & 0xfe0;
|
||||
for(auto& word : line.words) word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//16KB
|
||||
struct Line {
|
||||
auto hit(u32 address) const -> bool;
|
||||
auto fill(u32 address) -> void;
|
||||
auto writeBack() -> void;
|
||||
auto read(u32 address) const -> u32;
|
||||
auto hit(u32 address) const -> bool { return valid && tag == (address & ~0x0000'0fff); }
|
||||
auto fill(u32 address, CPU& cpu) -> void {
|
||||
cpu.step(48);
|
||||
valid = 1;
|
||||
tag = address & ~0x0000'0fff;
|
||||
words[0] = bus.read<Word>(tag | index | 0x00);
|
||||
words[1] = bus.read<Word>(tag | index | 0x04);
|
||||
words[2] = bus.read<Word>(tag | index | 0x08);
|
||||
words[3] = bus.read<Word>(tag | index | 0x0c);
|
||||
words[4] = bus.read<Word>(tag | index | 0x10);
|
||||
words[5] = bus.read<Word>(tag | index | 0x14);
|
||||
words[6] = bus.read<Word>(tag | index | 0x18);
|
||||
words[7] = bus.read<Word>(tag | index | 0x1c);
|
||||
}
|
||||
|
||||
auto writeBack(CPU& cpu) -> void {
|
||||
cpu.step(48);
|
||||
bus.write<Word>(tag | index | 0x00, words[0]);
|
||||
bus.write<Word>(tag | index | 0x04, words[1]);
|
||||
bus.write<Word>(tag | index | 0x08, words[2]);
|
||||
bus.write<Word>(tag | index | 0x0c, words[3]);
|
||||
bus.write<Word>(tag | index | 0x10, words[4]);
|
||||
bus.write<Word>(tag | index | 0x14, words[5]);
|
||||
bus.write<Word>(tag | index | 0x18, words[6]);
|
||||
bus.write<Word>(tag | index | 0x1c, words[7]);
|
||||
}
|
||||
|
||||
auto read(u32 address) const -> u32 { return words[address >> 2 & 7]; }
|
||||
|
||||
bool valid;
|
||||
u32 tag;
|
||||
u16 index;
|
||||
u32 words[8];
|
||||
} lines[512];
|
||||
} icache;
|
||||
} icache{*this};
|
||||
|
||||
//dcache.cpp
|
||||
struct DataCache {
|
||||
|
@ -705,12 +759,31 @@ struct CPU : Thread {
|
|||
}
|
||||
|
||||
auto invalidate(u32 address) -> void {
|
||||
/* FIXME: Recompiler shouldn't be so aggressive with pool eviction
|
||||
* Sometimes there are overlapping blocks, so clearing just one block
|
||||
* isn't sufficient and causes some games to crash (Jet Force Gemini)
|
||||
* the recompiler needs to be smarter with block tracking
|
||||
* Until then, clear the entire pool and live with the performance hit.
|
||||
*/
|
||||
#if 1
|
||||
invalidatePool(address);
|
||||
#else
|
||||
auto pool = pools[address >> 8 & 0x1fffff];
|
||||
if(!pool) return;
|
||||
memory::jitprotect(false);
|
||||
pool->blocks[address >> 2 & 0x3f] = nullptr;
|
||||
memory::jitprotect(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto invalidatePool(u32 address) -> void {
|
||||
pools[address >> 8 & 0x1fffff] = nullptr;
|
||||
}
|
||||
|
||||
auto invalidateRange(u32 address, u32 length) -> void {
|
||||
for (u32 s = 0; s < length; s += 256)
|
||||
invalidate(address + s);
|
||||
invalidate(address + length - 1);
|
||||
invalidatePool(address + s);
|
||||
invalidatePool(address + length - 1);
|
||||
}
|
||||
|
||||
auto pool(u32 address) -> Pool*;
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
auto CPU::InstructionCache::Line::hit(u32 address) const -> bool {
|
||||
return valid && tag == (address & ~0x0000'0fff);
|
||||
}
|
||||
|
||||
auto CPU::InstructionCache::Line::fill(u32 address) -> void {
|
||||
cpu.step(48);
|
||||
valid = 1;
|
||||
tag = address & ~0x0000'0fff;
|
||||
words[0] = bus.read<Word>(tag | index | 0x00);
|
||||
words[1] = bus.read<Word>(tag | index | 0x04);
|
||||
words[2] = bus.read<Word>(tag | index | 0x08);
|
||||
words[3] = bus.read<Word>(tag | index | 0x0c);
|
||||
words[4] = bus.read<Word>(tag | index | 0x10);
|
||||
words[5] = bus.read<Word>(tag | index | 0x14);
|
||||
words[6] = bus.read<Word>(tag | index | 0x18);
|
||||
words[7] = bus.read<Word>(tag | index | 0x1c);
|
||||
}
|
||||
|
||||
auto CPU::InstructionCache::Line::writeBack() -> void {
|
||||
cpu.step(48);
|
||||
bus.write<Word>(tag | index | 0x00, words[0]);
|
||||
bus.write<Word>(tag | index | 0x04, words[1]);
|
||||
bus.write<Word>(tag | index | 0x08, words[2]);
|
||||
bus.write<Word>(tag | index | 0x0c, words[3]);
|
||||
bus.write<Word>(tag | index | 0x10, words[4]);
|
||||
bus.write<Word>(tag | index | 0x14, words[5]);
|
||||
bus.write<Word>(tag | index | 0x18, words[6]);
|
||||
bus.write<Word>(tag | index | 0x1c, words[7]);
|
||||
}
|
||||
|
||||
auto CPU::InstructionCache::Line::read(u32 address) const -> u32 {
|
||||
return words[address >> 2 & 7];
|
||||
}
|
||||
|
||||
auto CPU::InstructionCache::line(u32 address) -> Line& {
|
||||
return lines[address >> 5 & 0x1ff];
|
||||
}
|
||||
|
||||
//used by the recompiler to simulate instruction cache fetch timing
|
||||
auto CPU::InstructionCache::step(u32 address) -> void {
|
||||
auto& line = this->line(address);
|
||||
if(!line.hit(address)) {
|
||||
cpu.step(48);
|
||||
line.valid = 1;
|
||||
line.tag = address & ~0x0000'0fff;
|
||||
} else {
|
||||
cpu.step(2);
|
||||
}
|
||||
}
|
||||
|
||||
//used by the interpreter to fully emulate the instruction cache
|
||||
auto CPU::InstructionCache::fetch(u32 address) -> u32 {
|
||||
auto& line = this->line(address);
|
||||
if(!line.hit(address)) {
|
||||
line.fill(address);
|
||||
} else {
|
||||
cpu.step(2);
|
||||
}
|
||||
return line.read(address);
|
||||
}
|
||||
|
||||
auto CPU::InstructionCache::power(bool reset) -> void {
|
||||
u32 index = 0;
|
||||
for(auto& line : lines) {
|
||||
line.valid = 0;
|
||||
line.tag = 0;
|
||||
line.index = index++ << 5 & 0xfe0;
|
||||
for(auto& word : line.words) word = 0;
|
||||
}
|
||||
}
|
|
@ -155,13 +155,13 @@ auto CPU::CACHE(u8 operation, cr64& rs, s16 imm) -> void {
|
|||
|
||||
case 0x14: { //icache fill
|
||||
auto& line = icache.line(address);
|
||||
line.fill(address);
|
||||
line.fill(address, cpu);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x18: { //icache hit write back
|
||||
auto& line = icache.line(address);
|
||||
if(line.hit(address)) line.writeBack();
|
||||
if(line.hit(address)) line.writeBack(cpu);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
|
|||
return 0; //nop
|
||||
case Context::Segment::Mapped:
|
||||
if(auto match = tlb.load(vaddr)) {
|
||||
if(match.cache) return icache.fetch(match.address & context.physMask);
|
||||
if(match.cache) return icache.fetch(match.address & context.physMask, cpu);
|
||||
step(1);
|
||||
return bus.read<Word>(match.address & context.physMask);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
|
|||
addressException(vaddr);
|
||||
return 0; //nop
|
||||
case Context::Segment::Cached:
|
||||
return icache.fetch(vaddr & context.physMask);
|
||||
return icache.fetch(vaddr & context.physMask, cpu);
|
||||
case Context::Segment::Direct:
|
||||
step(1);
|
||||
return bus.read<Word>(vaddr & context.physMask);
|
||||
|
|
|
@ -115,6 +115,7 @@ auto CPU::serialize(serializer& s) -> void {
|
|||
s(scc.tagLo.primaryCacheState);
|
||||
s(scc.tagLo.physicalAddress);
|
||||
s(scc.epcError);
|
||||
s(scc.latch);
|
||||
|
||||
for(auto& r : fpu.r) s(r.u64);
|
||||
s(fpu.csr.roundMode);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
//started: 2020-04-28
|
||||
|
||||
#define XXH_INLINE_ALL
|
||||
#include <xxhash.h>
|
||||
#include <ares/ares.hpp>
|
||||
#include <nall/hashset.hpp>
|
||||
#include <nall/recompiler/generic/generic.hpp>
|
||||
|
@ -9,6 +11,9 @@
|
|||
#if defined(ARCHITECTURE_AMD64)
|
||||
#include <nmmintrin.h>
|
||||
using v128 = __m128i;
|
||||
#elif defined(ARCHITECTURE_ARM64)
|
||||
#include <sse2neon.h>
|
||||
using v128 = __m128i;
|
||||
#endif
|
||||
|
||||
#if defined(VULKAN)
|
||||
|
|
|
@ -37,7 +37,7 @@ auto PI::dmaWrite() -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::CPU::Recompiler) {
|
||||
cpu.recompiler.invalidateRange(io.dramAddress, io.dramAddress + cur_len);
|
||||
cpu.recompiler.invalidateRange(io.dramAddress, cur_len);
|
||||
}
|
||||
for (u32 i = 0; i < cur_len; i++)
|
||||
rdram.ram.write<Byte>(io.dramAddress++, mem[i]);
|
||||
|
|
|
@ -50,9 +50,7 @@ auto RDP::render() -> void {
|
|||
#endif
|
||||
|
||||
#if defined(ANGRYLION_RDP)
|
||||
if (angrylion::ProcessRDPList()) {
|
||||
command.start = command.current = command.end;
|
||||
}
|
||||
command.current = angrylion::ProcessRDPList();
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ auto RDP::serialize(serializer& s) -> void {
|
|||
s(command.source);
|
||||
s(command.freeze);
|
||||
s(command.flush);
|
||||
s(command.startValid);
|
||||
s(command.endValid);
|
||||
s(command.startGclk);
|
||||
s(command.ready);
|
||||
|
||||
s(io.bist.check);
|
||||
|
|
|
@ -12,10 +12,11 @@ auto RSP::dmaTransferStep() -> void {
|
|||
auto& region = !dma.current.pbusRegion ? dmem : imem;
|
||||
|
||||
if(dma.busy.read) {
|
||||
if constexpr(Accuracy::RSP::Recompiler) {
|
||||
if(dma.current.pbusRegion) recompiler.invalidate();
|
||||
}
|
||||
for(u32 i = 0; i <= dma.current.length; i += 8) {
|
||||
if constexpr(Accuracy::RSP::Recompiler) {
|
||||
if(dma.current.pbusRegion) recompiler.invalidate(dma.current.pbusAddress);
|
||||
}
|
||||
|
||||
u64 data = rdram.ram.read<Dual>(dma.current.dramAddress);
|
||||
region.write<Dual>(dma.current.pbusAddress, data);
|
||||
dma.current.dramAddress += 8;
|
||||
|
|
|
@ -36,7 +36,6 @@ auto RSP::r128::operator()(u32 index) const -> r128 {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
static const __m128i shuffle[16] = {
|
||||
//vector
|
||||
_mm_set_epi8(15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), //01234567
|
||||
|
@ -61,7 +60,6 @@ auto RSP::r128::operator()(u32 index) const -> r128 {
|
|||
};
|
||||
//todo: benchmark to see if testing for cases 0&1 to return value directly is faster
|
||||
return {uint128_t(_mm_shuffle_epi8(v128, shuffle[index]))};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,10 +103,8 @@ auto RSP::CFC2(r32& rt, u8 rd) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
static const v128 reverse = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
rt.u32 = s16(_mm_movemask_epi8(_mm_shuffle_epi8(_mm_packs_epi16(hi, lo), reverse)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,11 +126,9 @@ auto RSP::CTC2(cr32& rt, u8 rd) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080);
|
||||
lo->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 0}, zero), mask), zero);
|
||||
hi->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 8}, zero), mask), zero);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,7 +481,6 @@ auto RSP::VABS(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vs0, slt;
|
||||
vs0 = _mm_cmpeq_epi16(vs, zero);
|
||||
slt = _mm_srai_epi16(vs, 15);
|
||||
|
@ -495,7 +488,6 @@ auto RSP::VABS(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
vd = _mm_xor_si128(vd, slt);
|
||||
ACCL = _mm_sub_epi16(vd, slt);
|
||||
vd = _mm_subs_epi16(vd, slt);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +505,6 @@ auto RSP::VADD(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sum, min, max;
|
||||
sum = _mm_add_epi16(vs, vte);
|
||||
ACCL = _mm_sub_epi16(sum, VCOL);
|
||||
|
@ -523,7 +514,6 @@ auto RSP::VADD(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
vd = _mm_adds_epi16(min, max);
|
||||
VCOL = zero;
|
||||
VCOH = zero;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +531,6 @@ auto RSP::VADDC(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sum;
|
||||
sum = _mm_adds_epu16(vs, vte);
|
||||
ACCL = _mm_add_epi16(vs, vte);
|
||||
|
@ -549,7 +538,6 @@ auto RSP::VADDC(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOL = _mm_cmpeq_epi16(VCOL, zero);
|
||||
VCOH = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,10 +552,8 @@ auto RSP::VAND(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_and_si128(vs, vt(e));
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -598,7 +584,6 @@ auto RSP::VCH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), nvt, diff, diff0, vtn, dlez, dgez, mask;
|
||||
VCOL = _mm_xor_si128(vs, vte);
|
||||
VCOL = _mm_cmplt_epi16(VCOL, zero);
|
||||
|
@ -619,7 +604,6 @@ auto RSP::VCH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
mask = _mm_blendv_epi8(VCCH, VCCL, VCOL);
|
||||
ACCL = _mm_blendv_epi8(vs, nvt, mask);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,7 +639,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), nvt, diff, ncarry, nvce, diff0, lec1, lec2, leeq, geeq, le, ge, mask;
|
||||
nvt = _mm_xor_si128(vte, VCOL);
|
||||
nvt = _mm_sub_epi16(nvt, VCOL);
|
||||
|
@ -683,7 +666,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOL = zero;
|
||||
VCE = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,7 +689,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sign, dlez, dgez, nvt, mask;
|
||||
sign = _mm_xor_si128(vs, vte);
|
||||
sign = _mm_srai_epi16(sign, 15);
|
||||
|
@ -724,7 +705,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOL = zero;
|
||||
VCOH = zero;
|
||||
VCE = zero;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,7 +722,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), eq;
|
||||
eq = _mm_cmpeq_epi16(vs, vte);
|
||||
VCCL = _mm_andnot_si128(VCOH, eq);
|
||||
|
@ -751,7 +730,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOH = zero;
|
||||
VCOL = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,7 +747,6 @@ auto RSP::VGE(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), eq, gt, es;
|
||||
eq = _mm_cmpeq_epi16(vs, vte);
|
||||
gt = _mm_cmpgt_epi16(vs, vte);
|
||||
|
@ -781,7 +758,6 @@ auto RSP::VGE(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOH = zero;
|
||||
VCOL = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,7 +775,6 @@ auto RSP::VLT(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), eq, lt;
|
||||
eq = _mm_cmpeq_epi16(vs, vte);
|
||||
lt = _mm_cmplt_epi16(vs, vte);
|
||||
|
@ -811,7 +786,6 @@ auto RSP::VLT(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOH = zero;
|
||||
VCOL = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -831,7 +805,6 @@ auto RSP::VMACF(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, md, hi, carry, omask;
|
||||
lo = _mm_mullo_epi16(vs, vte);
|
||||
hi = _mm_mulhi_epi16(vs, vte);
|
||||
|
@ -867,7 +840,6 @@ auto RSP::VMACF(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
md = _mm_andnot_si128(hmask, md);
|
||||
vd = _mm_or_si128(omask, md);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,7 +867,6 @@ auto RSP::VMADH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, hi, omask;
|
||||
lo = _mm_mullo_epi16(vs, vte);
|
||||
hi = _mm_mulhi_epi16(vs, vte);
|
||||
|
@ -908,7 +879,6 @@ auto RSP::VMADH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||
vd = _mm_packs_epi32(lo, hi);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -923,7 +893,6 @@ auto RSP::VMADL(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), hi, omask, nhi, nmd, shi, smd, cmask, cval;
|
||||
hi = _mm_mulhi_epu16(vs, vte);
|
||||
omask = _mm_adds_epu16(ACCL, hi);
|
||||
|
@ -943,7 +912,6 @@ auto RSP::VMADL(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
cmask = _mm_and_si128(smd, shi);
|
||||
cval = _mm_cmpeq_epi16(nhi, zero);
|
||||
vd = _mm_blendv_epi8(cval, ACCL, cmask);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,7 +926,6 @@ auto RSP::VMADM(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, hi, sign, vta, omask;
|
||||
lo = _mm_mullo_epi16(vs, vte);
|
||||
hi = _mm_mulhi_epu16(vs, vte);
|
||||
|
@ -980,7 +947,6 @@ auto RSP::VMADM(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||
vd = _mm_packs_epi32(lo, hi);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -995,7 +961,6 @@ auto RSP::VMADN(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, hi, sign, vsa, omask, nhi, nmd, shi, smd, cmask, cval;
|
||||
lo = _mm_mullo_epi16(vs, vte);
|
||||
hi = _mm_mulhi_epu16(vs, vte);
|
||||
|
@ -1021,7 +986,6 @@ auto RSP::VMADN(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
cmask = _mm_and_si128(smd, shi);
|
||||
cval = _mm_cmpeq_epi16(nhi, zero);
|
||||
vd = _mm_blendv_epi8(cval, ACCL, cmask);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1045,12 +1009,10 @@ auto RSP::VMRG(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_blendv_epi8(vt(e), vs, VCCL);
|
||||
VCOH = zero;
|
||||
VCOL = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1065,7 +1027,6 @@ auto RSP::VMUDH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, hi;
|
||||
ACCL = zero;
|
||||
ACCM = _mm_mullo_epi16(vs, vte);
|
||||
|
@ -1073,7 +1034,6 @@ auto RSP::VMUDH(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||
vd = _mm_packs_epi32(lo, hi);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,12 +1048,10 @@ auto RSP::VMUDL(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_mulhi_epu16(vs, vt(e));
|
||||
ACCM = zero;
|
||||
ACCH = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1108,7 +1066,6 @@ auto RSP::VMUDM(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sign, vta;
|
||||
ACCL = _mm_mullo_epi16(vs, vte);
|
||||
ACCM = _mm_mulhi_epu16(vs, vte);
|
||||
|
@ -1117,7 +1074,6 @@ auto RSP::VMUDM(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
ACCM = _mm_sub_epi16(ACCM, vta);
|
||||
ACCH = _mm_srai_epi16(ACCM, 15);
|
||||
vd = ACCM;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1132,7 +1088,6 @@ auto RSP::VMUDN(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sign, vsa;
|
||||
ACCL = _mm_mullo_epi16(vs, vte);
|
||||
ACCM = _mm_mulhi_epu16(vs, vte);
|
||||
|
@ -1141,7 +1096,6 @@ auto RSP::VMUDN(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
ACCM = _mm_sub_epi16(ACCM, vsa);
|
||||
ACCH = _mm_srai_epi16(ACCM, 15);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1161,7 +1115,6 @@ auto RSP::VMULF(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), lo, hi, round, sign1, sign2, neq, eq, neg;
|
||||
lo = _mm_mullo_epi16(vs, vte);
|
||||
round = _mm_cmpeq_epi16(zero, zero);
|
||||
|
@ -1185,7 +1138,6 @@ auto RSP::VMULF(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
hi = _mm_or_si128(ACCM, neg);
|
||||
vd = _mm_andnot_si128(ACCH, hi);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1213,11 +1165,9 @@ auto RSP::VNAND(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_and_si128(vs, vt(e));
|
||||
ACCL = _mm_xor_si128(ACCL, invert);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1235,7 +1185,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), eq, ne;
|
||||
eq = _mm_cmpeq_epi16(vs, vte);
|
||||
ne = _mm_cmpeq_epi16(eq, zero);
|
||||
|
@ -1246,7 +1195,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOH = zero;
|
||||
VCOL = zero;
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1264,11 +1212,9 @@ auto RSP::VNOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_or_si128(vs, vt(e));
|
||||
ACCL = _mm_xor_si128(ACCL, invert);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,11 +1229,9 @@ auto RSP::VNXOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_xor_si128(vs, vt(e));
|
||||
ACCL = _mm_xor_si128(ACCL, invert);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1302,10 +1246,8 @@ auto RSP::VOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_or_si128(vs, vt(e));
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1417,7 +1359,6 @@ auto RSP::VSUB(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), udiff, sdiff, ov;
|
||||
udiff = _mm_sub_epi16(vte, VCOL);
|
||||
sdiff = _mm_subs_epi16(vte, VCOL);
|
||||
|
@ -1427,7 +1368,6 @@ auto RSP::VSUB(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
vd = _mm_adds_epi16(vd, ov);
|
||||
VCOL = zero;
|
||||
VCOH = zero;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1445,7 +1385,6 @@ auto RSP::VSUBC(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), equal, udiff, diff0;
|
||||
udiff = _mm_subs_epu16(vs, vte);
|
||||
equal = _mm_cmpeq_epi16(vs, vte);
|
||||
|
@ -1454,7 +1393,6 @@ auto RSP::VSUBC(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
VCOL = _mm_andnot_si128(equal, diff0);
|
||||
ACCL = _mm_sub_epi16(vs, vte);
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1469,10 +1407,8 @@ auto RSP::VXOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
ACCL = _mm_xor_si128(vs, vt(e));
|
||||
vd = ACCL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1488,11 +1424,9 @@ auto RSP::VZERO(r128& vd, cr128& vs, cr128& vt) -> void {
|
|||
}
|
||||
|
||||
if constexpr(Accuracy::RSP::SIMD) {
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
r128 vte = vt(e), sum, min, max;
|
||||
ACCL = _mm_add_epi16(vs, vte);
|
||||
vd = _mm_xor_si128(vd, vd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ auto RSP::ioRead(u32 address) -> u32 {
|
|||
|
||||
auto RSP::writeWord(u32 address, u32 data) -> void {
|
||||
if(address <= 0x0403'ffff) {
|
||||
if(address & 0x1000) return recompiler.invalidate(), imem.write<Word>(address, data);
|
||||
if(address & 0x1000) return recompiler.invalidate(address & 0xfff), imem.write<Word>(address, data);
|
||||
else return dmem.write<Word>(address, data);
|
||||
}
|
||||
return ioWrite(address, data);
|
||||
|
|
|
@ -1,35 +1,34 @@
|
|||
auto RSP::Recompiler::pool() -> Pool* {
|
||||
if(context) return context;
|
||||
auto RSP::Recompiler::pool(u12 address) -> Pool* {
|
||||
if(context[address >> 8]) return context[address >> 8];
|
||||
|
||||
nall::Hash::CRC32 hashcode;
|
||||
for(u32 offset : range(4096)) {
|
||||
hashcode.input(self.imem.read<Byte>(offset));
|
||||
}
|
||||
auto hashcode = XXH3_64bits(self.imem.data + address, 256);
|
||||
|
||||
PoolHashPair pair;
|
||||
pair.pool = (Pool*)allocator.acquire();
|
||||
pair.hashcode = hashcode.value();
|
||||
if(auto result = pools.find(pair)) {
|
||||
return context = result->pool;
|
||||
pair.hashcode = hashcode;
|
||||
|
||||
auto result = pools[address >> 8].find(pair);
|
||||
if(result) {
|
||||
return context[address >> 8] = result->pool;
|
||||
}
|
||||
|
||||
allocator.reserve(sizeof(Pool));
|
||||
if(auto result = pools.insert(pair)) {
|
||||
return context = result->pool;
|
||||
if(auto result = pools[address >> 8].insert(pair)) {
|
||||
return context[address >> 8] = result->pool;
|
||||
}
|
||||
|
||||
throw; //should never occur
|
||||
}
|
||||
|
||||
auto RSP::Recompiler::block(u32 address) -> Block* {
|
||||
if(auto block = pool()->blocks[address >> 2 & 0x3ff]) return block;
|
||||
auto RSP::Recompiler::block(u12 address) -> Block* {
|
||||
if(auto block = pool(address)->blocks[address >> 2 & 0x3ff]) return block;
|
||||
auto block = emit(address);
|
||||
pool()->blocks[address >> 2 & 0x3ff] = block;
|
||||
pool(address)->blocks[address >> 2 & 0x3ff] = block;
|
||||
memory::jitprotect(true);
|
||||
return block;
|
||||
}
|
||||
|
||||
auto RSP::Recompiler::emit(u32 address) -> Block* {
|
||||
auto RSP::Recompiler::emit(u12 address) -> Block* {
|
||||
if(unlikely(allocator.available() < 1_MiB)) {
|
||||
print("RSP allocator flush\n");
|
||||
memory::jitprotect(false);
|
||||
|
|
|
@ -108,7 +108,7 @@ struct RSP : Thread, Memory::IO<RSP> {
|
|||
};
|
||||
|
||||
r32 r[32];
|
||||
u12 pc;
|
||||
u16 pc; // previously u12; now u16 for performance.
|
||||
} ipu;
|
||||
|
||||
struct Branch {
|
||||
|
@ -175,7 +175,7 @@ struct RSP : Thread, Memory::IO<RSP> {
|
|||
//vpu.cpp: Vector Processing Unit
|
||||
union r128 {
|
||||
struct { uint128_t u128; };
|
||||
#if defined(ARCHITECTURE_AMD64)
|
||||
#if defined(ARCHITECTURE_AMD64) || defined(ARCHITECTURE_ARM64)
|
||||
struct { __m128i v128; };
|
||||
|
||||
operator __m128i() const { return v128; }
|
||||
|
@ -350,18 +350,18 @@ struct RSP : Thread, Memory::IO<RSP> {
|
|||
};
|
||||
|
||||
auto reset() -> void {
|
||||
context = nullptr;
|
||||
pools.reset();
|
||||
for(auto n : range(16)) context[n] = nullptr;
|
||||
for(auto n : range(16)) pools[n].reset();
|
||||
}
|
||||
|
||||
auto invalidate() -> void {
|
||||
context = nullptr;
|
||||
auto invalidate(u32 address) -> void {
|
||||
context[address >> 8] = nullptr;
|
||||
}
|
||||
|
||||
auto pool() -> Pool*;
|
||||
auto block(u32 address) -> Block*;
|
||||
auto pool(u12 address) -> Pool*;
|
||||
auto block(u12 address) -> Block*;
|
||||
|
||||
auto emit(u32 address) -> Block*;
|
||||
auto emit(u12 address) -> Block*;
|
||||
auto emitEXECUTE(u32 instruction) -> bool;
|
||||
auto emitSPECIAL(u32 instruction) -> bool;
|
||||
auto emitREGIMM(u32 instruction) -> bool;
|
||||
|
@ -371,9 +371,8 @@ struct RSP : Thread, Memory::IO<RSP> {
|
|||
auto emitSWC2(u32 instruction) -> bool;
|
||||
|
||||
bump_allocator allocator;
|
||||
Pool* context = nullptr;
|
||||
set<PoolHashPair> pools;
|
||||
//hashset<PoolHashPair> pools;
|
||||
Pool* context[16];
|
||||
set<PoolHashPair> pools[16];
|
||||
} recompiler{*this};
|
||||
|
||||
struct Disassembler {
|
||||
|
|
|
@ -1,298 +0,0 @@
|
|||
# disable built-in rules and variables
|
||||
MAKEFLAGS := Rr
|
||||
.SUFFIXES:
|
||||
|
||||
[0-9] = 0 1 2 3 4 5 6 7 8 9
|
||||
[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|
||||
[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z
|
||||
[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ?
|
||||
[all] = $([0-9]) $([A-Z]) $([a-z]) $([markup])
|
||||
[empty] :=
|
||||
[space] := $([empty]) $([empty])
|
||||
|
||||
# platform detection
|
||||
ifeq ($(platform),)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
platform := windows
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(platform),)
|
||||
uname := $(shell uname)
|
||||
ifeq ($(uname),)
|
||||
platform := windows
|
||||
else ifneq ($(findstring Windows,$(uname)),)
|
||||
platform := windows
|
||||
else ifneq ($(findstring NT,$(uname)),)
|
||||
platform := windows
|
||||
else ifneq ($(findstring Darwin,$(uname)),)
|
||||
platform := macos
|
||||
else ifneq ($(findstring Linux,$(uname)),)
|
||||
platform := linux
|
||||
else ifneq ($(findstring BSD,$(uname)),)
|
||||
platform := bsd
|
||||
else
|
||||
$(error unknown platform, please specify manually.)
|
||||
endif
|
||||
endif
|
||||
|
||||
# common commands
|
||||
ifeq ($(shell echo ^^),^)
|
||||
# cmd
|
||||
fixpath = $(subst /,\\,$1)
|
||||
mkdir = @if not exist $(call fixpath,$1) (mkdir $(call fixpath,$1))
|
||||
copy = @copy $(call fixpath,$1) $(call fixpath,$2)
|
||||
rcopy = @xcopy /e /q /y $(call fixpath,$1) $(call fixpath,$2)
|
||||
delete = $(info Deleting $1 ...) @del /q $(call fixpath,$1)
|
||||
rdelete = $(info Deleting $1 ...) @if exist $(call fixpath,$1) (rmdir /s /q $(call fixpath,$1))
|
||||
else
|
||||
# sh
|
||||
mkdir = @mkdir -p $1
|
||||
copy = @cp $1 $2
|
||||
rcopy = @cp -R $1 $2
|
||||
delete = $(info Deleting $1 ...) @rm -f $1
|
||||
rdelete = $(info Deleting $1 ...) @rm -rf $1
|
||||
endif
|
||||
|
||||
compiler.c = $(compiler) -x c -std=c11
|
||||
compiler.cpp = $(compiler) -x c++ -std=c++17 -fno-operator-names
|
||||
compiler.objc = $(compiler) -x objective-c -std=c11
|
||||
compiler.objcpp = $(compiler) -x objective-c++ -std=c++17 -fno-operator-names
|
||||
|
||||
flags.c = -x c -std=c11
|
||||
flags.cpp = -x c++ -std=c++17 -fno-operator-names
|
||||
flags.objc = -x objective-c -std=c11
|
||||
flags.objcpp = -x objective-c++ -std=c++17 -fno-operator-names
|
||||
flags.deps = -MMD -MP -MF $(@:.o=.d)
|
||||
|
||||
# compiler detection
|
||||
ifeq ($(compiler),)
|
||||
ifeq ($(platform),windows)
|
||||
compiler := g++
|
||||
compiler.cpp = $(compiler) -x c++ -std=gnu++17 -fno-operator-names
|
||||
flags.cpp = -x c++ -std=gnu++17 -fno-operator-names
|
||||
else ifeq ($(platform),macos)
|
||||
compiler := clang++
|
||||
else ifeq ($(platform),linux)
|
||||
compiler := g++
|
||||
else ifeq ($(platform),bsd)
|
||||
compiler := clang++
|
||||
else
|
||||
compiler := g++
|
||||
endif
|
||||
endif
|
||||
|
||||
# architecture detection
|
||||
ifeq ($(arch),)
|
||||
machine := $(shell $(compiler) -dumpmachine)
|
||||
ifneq ($(filter amd64-% x86_64-%,$(machine)),)
|
||||
arch := amd64
|
||||
else ifneq ($(filter arm64-% aarch64-%,$(machine)),)
|
||||
arch := arm64
|
||||
else
|
||||
$(error unknown arch, please specify manually.)
|
||||
endif
|
||||
endif
|
||||
|
||||
# build optimization levels
|
||||
ifeq ($(build),debug)
|
||||
symbols = true
|
||||
flags += -Og -DBUILD_DEBUG
|
||||
else ifeq ($(build),stable)
|
||||
flags += -O1 -DBUILD_STABLE
|
||||
else ifeq ($(build),minified)
|
||||
flags += -Os -DBUILD_MINIFIED
|
||||
else ifeq ($(build),release)
|
||||
flags += -O2 -DBUILD_RELEASE
|
||||
else ifeq ($(build),optimized)
|
||||
flags += -O3 -fomit-frame-pointer -DBUILD_OPTIMIZED
|
||||
else
|
||||
$(error unrecognized build type.)
|
||||
endif
|
||||
|
||||
# debugging information
|
||||
ifeq ($(symbols),true)
|
||||
flags += -g
|
||||
ifeq ($(platform),windows)
|
||||
ifeq ($(findstring clang++,$(compiler)),clang++)
|
||||
flags += -gcodeview
|
||||
options += -Wl,-pdb=
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# link-time optimization
|
||||
ifeq ($(lto),true)
|
||||
flags += -flto
|
||||
options += -fwhole-program
|
||||
ifneq ($(findstring clang++,$(compiler)),clang++)
|
||||
flags += -fwhole-program -fno-fat-lto-objects
|
||||
options += -flto=jobserver
|
||||
else
|
||||
options += -flto=thin
|
||||
endif
|
||||
endif
|
||||
|
||||
# openmp support
|
||||
ifeq ($(openmp),true)
|
||||
# macOS Xcode does not ship with OpenMP support
|
||||
ifneq ($(platform),macos)
|
||||
flags += -fopenmp
|
||||
options += -fopenmp
|
||||
endif
|
||||
endif
|
||||
|
||||
# clang settings
|
||||
ifeq ($(findstring clang++,$(compiler)),clang++)
|
||||
flags += -fno-strict-aliasing -fwrapv
|
||||
ifeq ($(arch),arm64)
|
||||
# work around bad interaction with alignas(n) when n >= 4096
|
||||
flags += -mno-global-merge
|
||||
endif
|
||||
# gcc settings
|
||||
else ifeq ($(findstring g++,$(compiler)),g++)
|
||||
flags += -fno-strict-aliasing -fwrapv -Wno-trigraphs
|
||||
endif
|
||||
|
||||
# windows settings
|
||||
ifeq ($(platform),windows)
|
||||
options += -mthreads -lpthread -lws2_32 -lole32
|
||||
options += $(if $(findstring clang++,$(compiler)),-fuse-ld=lld)
|
||||
options += $(if $(findstring g++,$(compiler)),-static -static-libgcc -static-libstdc++)
|
||||
options += $(if $(findstring true,$(console)),-mconsole,-mwindows)
|
||||
windres := windres
|
||||
endif
|
||||
|
||||
# macos settings
|
||||
ifeq ($(platform),macos)
|
||||
flags += -stdlib=libc++ -mmacosx-version-min=10.9 -Wno-auto-var-id -fobjc-arc
|
||||
options += -lc++ -lobjc -mmacosx-version-min=10.9
|
||||
# allow mprotect() on dynamic recompiler code blocks
|
||||
options += -Wl,-segprot,__DATA,rwx,rw
|
||||
endif
|
||||
|
||||
# linux settings
|
||||
ifeq ($(platform),linux)
|
||||
options += -ldl
|
||||
endif
|
||||
|
||||
# bsd settings
|
||||
ifeq ($(platform),bsd)
|
||||
flags += -I/usr/local/include
|
||||
options += -Wl,-rpath=/usr/local/lib
|
||||
options += -Wl,-rpath=/usr/local/lib/gcc8
|
||||
options += -lstdc++ -lm
|
||||
endif
|
||||
|
||||
# threading support
|
||||
ifeq ($(threaded),true)
|
||||
ifneq ($(filter $(platform),linux bsd),)
|
||||
flags += -pthread
|
||||
options += -pthread -lrt
|
||||
endif
|
||||
endif
|
||||
|
||||
# paths
|
||||
ifeq ($(object.path),)
|
||||
object.path := obj
|
||||
endif
|
||||
|
||||
ifeq ($(output.path),)
|
||||
output.path := out
|
||||
endif
|
||||
|
||||
# rules
|
||||
default: all;
|
||||
|
||||
nall.verbose:
|
||||
$(info Compiler Flags:)
|
||||
$(foreach n,$(sort $(call unique,$(flags))),$(if $(filter-out -I%,$n),$(info $([space]) $n)))
|
||||
$(info Linker Options:)
|
||||
$(foreach n,$(sort $(call unique,$(options))),$(if $(filter-out -l%,$n),$(info $([space]) $n)))
|
||||
|
||||
%.o: $<
|
||||
$(info Compiling $(subst ../,,$<) ...)
|
||||
@$(call compile)
|
||||
|
||||
$(object.path):
|
||||
$(call mkdir,$(object.path))
|
||||
|
||||
$(output.path):
|
||||
$(call mkdir,$(output.path))
|
||||
|
||||
# function compile([arguments])
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(compiler.c) $(flags.deps) $(flags) $1 -c $< -o $@ \
|
||||
,$(if $(filter %.cpp,$<), \
|
||||
$(compiler.cpp) $(flags.deps) $(flags) $1 -c $< -o $@ \
|
||||
)) \
|
||||
)
|
||||
|
||||
# function rwildcard(directory, pattern)
|
||||
rwildcard = \
|
||||
$(strip \
|
||||
$(filter $(if $2,$2,%), \
|
||||
$(foreach f, \
|
||||
$(wildcard $1*), \
|
||||
$(eval t = $(call rwildcard,$f/)) \
|
||||
$(if $t,$t,$f) \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
# function unique(source)
|
||||
unique = \
|
||||
$(eval __temp :=) \
|
||||
$(strip \
|
||||
$(foreach s,$1,$(if $(filter $s,$(__temp)),,$(eval __temp += $s))) \
|
||||
$(__temp) \
|
||||
)
|
||||
|
||||
# function strtr(source, from, to)
|
||||
strtr = \
|
||||
$(eval __temp := $1) \
|
||||
$(strip \
|
||||
$(foreach c, \
|
||||
$(join $(addsuffix :,$2),$3), \
|
||||
$(eval __temp := \
|
||||
$(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \
|
||||
) \
|
||||
) \
|
||||
$(__temp) \
|
||||
)
|
||||
|
||||
# function strupper(source)
|
||||
strupper = $(call strtr,$1,$([a-z]),$([A-Z]))
|
||||
|
||||
# function strlower(source)
|
||||
strlower = $(call strtr,$1,$([A-Z]),$([a-z]))
|
||||
|
||||
# function strlen(source)
|
||||
strlen = \
|
||||
$(eval __temp := $(subst $([space]),_,$1)) \
|
||||
$(words \
|
||||
$(strip \
|
||||
$(foreach c, \
|
||||
$([all]), \
|
||||
$(eval __temp := \
|
||||
$(subst $c,$c ,$(__temp)) \
|
||||
) \
|
||||
) \
|
||||
$(__temp) \
|
||||
) \
|
||||
)
|
||||
|
||||
# function streq(source)
|
||||
streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1)
|
||||
|
||||
# function strne(source)
|
||||
strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,)
|
||||
|
||||
# prefix
|
||||
ifeq ($(platform),windows)
|
||||
prefix := $(subst $([space]),\$([space]),$(strip $(call strtr,$(LOCALAPPDATA),\,/)))
|
||||
else
|
||||
prefix := $(HOME)/.local
|
||||
endif
|
|
@ -199,7 +199,7 @@ namespace nall {
|
|||
struct Architecture {
|
||||
static constexpr bool x86 = 0;
|
||||
static constexpr bool amd64 = 0;
|
||||
static constexpr bool sse41 = 0;
|
||||
static constexpr bool sse41 = 1; // simulated via sse2neon.h
|
||||
static constexpr bool arm64 = 1;
|
||||
static constexpr bool arm32 = 0;
|
||||
static constexpr bool ppc64 = 0;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit fd4173287f22271908b82148470e4e1e34707228
|
||||
Subproject commit 5dc6921aba40fcc94e9578e93a16ab8ba402d0f8
|
|
@ -1,5 +1,9 @@
|
|||
This file is the short summary of the API changes:
|
||||
|
||||
16.06.2022 - Non-backward compatible
|
||||
Remove SLJIT_ENTER_CDECL and SLJIT_CALL_CDECL.
|
||||
The default calling mode is cdecl now.
|
||||
|
||||
21.04.2022 - Non-backward compatible
|
||||
Floating point comparison types are renamed.
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ SLJIT_LIR_FILES = $(SRCDIR)/sljitLir.c $(SRCDIR)/sljitUtils.c \
|
|||
$(SRCDIR)/sljitNativeARM_32.c $(SRCDIR)/sljitNativeARM_T2_32.c $(SRCDIR)/sljitNativeARM_64.c \
|
||||
$(SRCDIR)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \
|
||||
$(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_64.c \
|
||||
$(SRCDIR)/sljitNativeSPARC_common.c $(SRCDIR)/sljitNativeSPARC_32.c \
|
||||
$(SRCDIR)/sljitNativeRISCV_common.c $(SRCDIR)/sljitNativeRISCV_32.c $(SRCDIR)/sljitNativeRISCV_64.c \
|
||||
$(SRCDIR)/sljitNativeS390X.c \
|
||||
$(SRCDIR)/sljitNativeX86_common.c $(SRCDIR)/sljitNativeX86_32.c $(SRCDIR)/sljitNativeX86_64.c
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ extern "C" {
|
|||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_64 1 */
|
||||
/* #define SLJIT_CONFIG_SPARC_32 1 */
|
||||
/* #define SLJIT_CONFIG_RISCV_32 1 */
|
||||
/* #define SLJIT_CONFIG_RISCV_64 1 */
|
||||
/* #define SLJIT_CONFIG_S390X 1 */
|
||||
|
||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||
|
@ -127,17 +128,6 @@ extern "C" {
|
|||
|
||||
#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
|
||||
|
||||
/* Force cdecl calling convention even if a better calling
|
||||
convention (e.g. fastcall) is supported by the C compiler.
|
||||
If this option is disabled (this is the default), functions
|
||||
called from JIT should be defined with SLJIT_FUNC attribute.
|
||||
Standard C functions can still be called by using the
|
||||
SLJIT_CALL_CDECL jump type. */
|
||||
#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
|
||||
/* Disabled by default */
|
||||
#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
|
||||
#endif
|
||||
|
||||
/* Return with error when an invalid argument is passed. */
|
||||
#ifndef SLJIT_ARGUMENT_CHECKS
|
||||
/* Disabled by default */
|
||||
|
|
|
@ -59,7 +59,8 @@ extern "C" {
|
|||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||
SLJIT_BIG_ENDIAN : big endian architecture
|
||||
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
|
||||
SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported
|
||||
SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported
|
||||
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
|
||||
|
||||
Constants:
|
||||
|
@ -100,7 +101,6 @@ extern "C" {
|
|||
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||
+ (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
||||
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
+ (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
|
@ -119,7 +119,6 @@ extern "C" {
|
|||
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
||||
&& !(defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|
||||
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
|
||||
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||
|
@ -164,8 +163,6 @@ extern "C" {
|
|||
#define SLJIT_CONFIG_RISCV_32 1
|
||||
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
|
||||
#define SLJIT_CONFIG_RISCV_64 1
|
||||
#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64)
|
||||
#define SLJIT_CONFIG_SPARC_32 1
|
||||
#elif defined(__s390x__)
|
||||
#define SLJIT_CONFIG_S390X 1
|
||||
#else
|
||||
|
@ -215,8 +212,6 @@ extern "C" {
|
|||
#define SLJIT_CONFIG_MIPS 1
|
||||
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
||||
#define SLJIT_CONFIG_RISCV 1
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
|
||||
#define SLJIT_CONFIG_SPARC 1
|
||||
#endif
|
||||
|
||||
/***********************************************************/
|
||||
|
@ -355,9 +350,9 @@ extern "C" {
|
|||
/*
|
||||
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
|
||||
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
|
||||
* gcc's clear_cache builtin for power and sparc are broken
|
||||
* gcc's clear_cache builtin for power is broken
|
||||
*/
|
||||
#if !defined(SLJIT_CONFIG_PPC) && !defined(SLJIT_CONFIG_SPARC_32)
|
||||
#if !defined(SLJIT_CONFIG_PPC)
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
__builtin___clear_cache((char*)(from), (char*)(to))
|
||||
#endif
|
||||
|
@ -389,13 +384,6 @@ extern "C" {
|
|||
ppc_cache_flush((from), (to))
|
||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
sparc_cache_flush((from), (to))
|
||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||
|
@ -512,8 +500,7 @@ typedef double sljit_f64;
|
|||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are mostly useful for the applications. */
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
|
@ -521,8 +508,7 @@ typedef double sljit_f64;
|
|||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
||||
#ifdef __MIPSEL__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
|
@ -549,8 +535,7 @@ typedef double sljit_f64;
|
|||
|
||||
#endif /* !SLJIT_MIPS_REV */
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
|
@ -583,6 +568,18 @@ typedef double sljit_f64;
|
|||
|
||||
#endif /* !SLJIT_UNALIGNED */
|
||||
|
||||
#ifndef SLJIT_FPU_UNALIGNED
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
#define SLJIT_FPU_UNALIGNED 1
|
||||
#endif
|
||||
|
||||
#endif /* !SLJIT_FPU_UNALIGNED */
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
/* Auto detect SSE2 support using CPUID.
|
||||
On 64 bit x86 cpus, sse2 must be present. */
|
||||
|
@ -594,38 +591,7 @@ typedef double sljit_f64;
|
|||
/*****************************************************************************************/
|
||||
|
||||
#ifndef SLJIT_FUNC
|
||||
|
||||
#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \
|
||||
|| !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#define SLJIT_FUNC
|
||||
|
||||
#elif defined(__GNUC__) && !defined(__APPLE__)
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
#define SLJIT_FUNC __attribute__ ((fastcall))
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
#else
|
||||
#define SLJIT_FUNC
|
||||
#endif /* gcc >= 3.4 */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define SLJIT_FUNC __fastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
#define SLJIT_FUNC __msfastcall
|
||||
#define SLJIT_X86_32_FASTCALL 1
|
||||
|
||||
#else /* Unknown compiler. */
|
||||
|
||||
/* The cdecl calling convention is usually the x86 default. */
|
||||
#define SLJIT_FUNC
|
||||
|
||||
#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */
|
||||
|
||||
#endif /* !SLJIT_FUNC */
|
||||
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
|
@ -640,11 +606,7 @@ typedef double sljit_f64;
|
|||
/* The offset which needs to be substracted from the return address to
|
||||
determine the next executed instruction after return. */
|
||||
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 8
|
||||
#else
|
||||
#define SLJIT_RETURN_ADDRESS_OFFSET 0
|
||||
#endif
|
||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
||||
|
||||
/***************************************************/
|
||||
|
@ -682,10 +644,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw))
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||
|
||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
@ -699,7 +661,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
#else /* _WIN64 */
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw))
|
||||
#endif /* !_WIN64 */
|
||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
|
||||
|
||||
|
@ -764,18 +726,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 18
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
|
||||
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
|
||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
/* saved registers (16), return struct pointer (1), space for 6 argument words (1),
|
||||
4th double arg (2), double alignment (1). */
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * (sljit_s32)sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
|
||||
/*
|
||||
|
@ -831,7 +781,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||
|| (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \
|
||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
|
||||
#endif
|
||||
|
|
|
@ -148,16 +148,16 @@
|
|||
# define PATCH_MD 0x10
|
||||
#endif
|
||||
# define TYPE_SHIFT 13
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_X86 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
# define IS_BL 0x4
|
||||
# define PATCH_B 0x8
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
# define CPOOL_SIZE 512
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
# define IS_COND 0x04
|
||||
|
@ -175,7 +175,7 @@
|
|||
/* BL + imm24 */
|
||||
# define PATCH_BL 0x60
|
||||
/* 0xf00 cc code for branches */
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_ARM_THUMB2 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
# define IS_COND 0x004
|
||||
|
@ -185,7 +185,7 @@
|
|||
# define PATCH_COND 0x040
|
||||
# define PATCH_ABS48 0x080
|
||||
# define PATCH_ABS64 0x100
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_ARM_64 */
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
# define IS_COND 0x004
|
||||
|
@ -195,9 +195,9 @@
|
|||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# define PATCH_ABS32 0x040
|
||||
# define PATCH_ABS48 0x080
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_PPC_64 */
|
||||
# define REMOVE_COND 0x100
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_PPC */
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
# define IS_MOVABLE 0x004
|
||||
|
@ -215,7 +215,7 @@
|
|||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
# define PATCH_ABS32 0x400
|
||||
# define PATCH_ABS48 0x800
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_MIPS_64 */
|
||||
|
||||
/* instruction types */
|
||||
# define MOVABLE_INS 0
|
||||
|
@ -224,7 +224,7 @@
|
|||
# define UNMOVABLE_INS 32
|
||||
/* FPU status register */
|
||||
# define FCSR_FCC 33
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_MIPS */
|
||||
|
||||
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||
# define IS_COND 0x004
|
||||
|
@ -241,28 +241,7 @@
|
|||
#else /* !SLJIT_CONFIG_RISCV_64 */
|
||||
# define PATCH_REL32 0x0
|
||||
#endif /* SLJIT_CONFIG_RISCV_64 */
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
# define IS_MOVABLE 0x04
|
||||
# define IS_COND 0x08
|
||||
# define IS_CALL 0x10
|
||||
|
||||
# define PATCH_B 0x20
|
||||
# define PATCH_CALL 0x40
|
||||
|
||||
/* instruction types */
|
||||
# define MOVABLE_INS 0
|
||||
/* 1 - 31 last destination register */
|
||||
/* no destination (i.e: store) */
|
||||
# define UNMOVABLE_INS 32
|
||||
|
||||
# define DST_INS_MASK 0xff
|
||||
|
||||
/* ICC_SET is the same as SET_FLAGS. */
|
||||
# define ICC_IS_SET (1 << 23)
|
||||
# define FCC_IS_SET (1 << 24)
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_RISCV */
|
||||
|
||||
/* Stack management. */
|
||||
|
||||
|
@ -457,10 +436,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
|
|||
compiler->delay_slot = UNMOVABLE_INS;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
compiler->delay_slot = UNMOVABLE_INS;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
compiler->last_flags = 0;
|
||||
|
@ -842,6 +817,9 @@ static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s
|
|||
if (!(p & SLJIT_MEM))
|
||||
return 0;
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
|
||||
return 0;
|
||||
|
||||
|
@ -879,9 +857,6 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p
|
|||
if (p == SLJIT_IMM)
|
||||
return 1;
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
|
@ -896,9 +871,6 @@ static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p
|
|||
if (FUNCTION_CHECK_IS_REG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
|
@ -913,9 +885,6 @@ static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, s
|
|||
if (FUNCTION_CHECK_IS_FREG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1032,7 @@ static const char* jump_names[] = {
|
|||
"unordered_or_less", "ordered_greater_equal",
|
||||
"unordered_or_greater", "ordered_less_equal",
|
||||
"jump", "fast_call",
|
||||
"call", "call.cdecl"
|
||||
"call", "call_reg_arg"
|
||||
};
|
||||
|
||||
static const char* call_arg_names[] = {
|
||||
|
@ -1079,6 +1048,8 @@ static const char* call_arg_names[] = {
|
|||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
||||
#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
|
@ -1106,8 +1077,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
|
|||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
|
||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
||||
if (options & SLJIT_ENTER_REG_ARG) {
|
||||
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
|
||||
} else {
|
||||
CHECK_ARGUMENT(options == 0);
|
||||
}
|
||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
||||
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
|
@ -1116,7 +1091,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
|
|||
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), fscratches));
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
|
||||
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
|
@ -1138,10 +1113,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
|
|||
|
||||
fprintf(compiler->verbose, "],");
|
||||
|
||||
if (options & SLJIT_ENTER_CDECL)
|
||||
fprintf(compiler->verbose, " enter:cdecl,");
|
||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
||||
if (options & SLJIT_ENTER_REG_ARG) {
|
||||
fprintf(compiler->verbose, " enter:reg_arg,");
|
||||
|
||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, "scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
|
||||
scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
@ -1157,8 +1134,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
|
|||
SLJIT_UNUSED_ARG(compiler);
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
|
||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
||||
if (options & SLJIT_ENTER_REG_ARG) {
|
||||
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
|
||||
} else {
|
||||
CHECK_ARGUMENT(options == 0);
|
||||
}
|
||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
||||
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
|
||||
|
@ -1167,7 +1148,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
|
|||
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), fscratches));
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
|
||||
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
|
@ -1189,10 +1170,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
|
|||
|
||||
fprintf(compiler->verbose, "],");
|
||||
|
||||
if (options & SLJIT_ENTER_CDECL)
|
||||
fprintf(compiler->verbose, " enter:cdecl,");
|
||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
||||
if (options & SLJIT_ENTER_REG_ARG) {
|
||||
fprintf(compiler->verbose, " enter:reg_arg,");
|
||||
|
||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
|
||||
scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
@ -1737,11 +1720,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile
|
|||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
|
||||
|
||||
if (compiler->options & SLJIT_ENTER_REG_ARG) {
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
|
||||
} else {
|
||||
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
@ -1845,12 +1834,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil
|
|||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
|
||||
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
|
||||
|
||||
if (compiler->options & SLJIT_ENTER_REG_ARG) {
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
|
||||
} else {
|
||||
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
@ -1954,27 +1949,63 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
|
|||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
sljit_s32 allowed_flags;
|
||||
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
|
||||
CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED) {
|
||||
allowed_flags = SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32;
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
allowed_flags = 0;
|
||||
break;
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV32:
|
||||
allowed_flags = SLJIT_MEM_ALIGNED_16;
|
||||
break;
|
||||
}
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | allowed_flags)) == 0);
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32));
|
||||
} else {
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
|
||||
}
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
|
||||
|
||||
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
|
||||
if (type & SLJIT_MEM_SUPP)
|
||||
CHECK_RETURN_OK;
|
||||
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
|
||||
fprintf(compiler->verbose, " // mem: unsupported form, no instructions are emitted");
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, " mem%s.%s%s%s ",
|
||||
!(type & SLJIT_32) ? "" : "32",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
if ((type & 0xff) == SLJIT_MOV32)
|
||||
fprintf(compiler->verbose, " mem32.%s",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld");
|
||||
else
|
||||
fprintf(compiler->verbose, " mem%s.%s%s",
|
||||
!(type & SLJIT_32) ? "" : "32",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
op1_names[(type & 0xff) - SLJIT_OP1_BASE]);
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED) {
|
||||
printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : "");
|
||||
} else
|
||||
printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post ");
|
||||
sljit_verbose_reg(compiler, reg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
|
@ -1990,22 +2021,37 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile
|
|||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
if (type & SLJIT_MEM_UNALIGNED) {
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | (type & SLJIT_32 ? 0 : SLJIT_MEM_ALIGNED_32))) == 0);
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32));
|
||||
} else {
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
}
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
|
||||
if (type & SLJIT_MEM_SUPP)
|
||||
CHECK_RETURN_OK;
|
||||
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
|
||||
fprintf(compiler->verbose, " // fmem: unsupported form, no instructions are emitted");
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(compiler->verbose, " fmem.%s%s%s ",
|
||||
fprintf(compiler->verbose, " fmem.%s%s",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
!(type & SLJIT_32) ? ".f64" : ".f32",
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
!(type & SLJIT_32) ? ".f64" : ".f32");
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED) {
|
||||
printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : "");
|
||||
} else
|
||||
printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post ");
|
||||
sljit_verbose_freg(compiler, freg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
|
@ -2065,6 +2111,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co
|
|||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */
|
||||
|
||||
#define SLJIT_SKIP_CHECKS(compiler)
|
||||
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
|
||||
|
||||
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
|
||||
|
@ -2103,15 +2153,10 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
|
|||
return SLJIT_SUCCESS;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
|
@ -2119,18 +2164,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
|
|||
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_return_void(compiler);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
|| ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \
|
||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||
|
||||
|
@ -2142,31 +2181,55 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
|
|||
struct sljit_jump *jump;
|
||||
sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
jump = sljit_emit_jump(compiler, type ^ 0x1);
|
||||
FAIL_IF(!jump);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
label = sljit_emit_label(compiler);
|
||||
FAIL_IF(!label);
|
||||
|
||||
sljit_set_label(jump, label);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
|
||||
static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
|
||||
if (type & SLJIT_MEM_STORE)
|
||||
return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0);
|
||||
return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw);
|
||||
}
|
||||
|
||||
#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM_V5 */
|
||||
|
||||
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
|
||||
|
||||
static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
|
||||
if (type & SLJIT_MEM_STORE)
|
||||
return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0);
|
||||
return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw);
|
||||
}
|
||||
|
||||
#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */
|
||||
|
||||
/* CPU description section */
|
||||
|
||||
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
|
||||
|
@ -2209,8 +2272,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
|
|||
# include "sljitNativeMIPS_common.c"
|
||||
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||
# include "sljitNativeRISCV_common.c"
|
||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
||||
# include "sljitNativeSPARC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
# include "sljitNativeS390X.c"
|
||||
#endif
|
||||
|
@ -2286,16 +2347,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
|||
else
|
||||
flags = condition << VARIABLE_FLAG_SHIFT;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
PTR_FAIL_IF(sljit_emit_op2u(compiler,
|
||||
SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));
|
||||
}
|
||||
|
||||
|
@ -2326,58 +2382,47 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
|||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|
||||
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|
||||
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(freg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2391,10 +2436,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
|
|||
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
|
||||
|
||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
|
||||
if (offset != 0)
|
||||
return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
|
||||
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
|
||||
|
|
|
@ -446,8 +446,6 @@ struct sljit_compiler {
|
|||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_s32 args_size;
|
||||
sljit_s32 locals_offset;
|
||||
sljit_s32 scratches_offset;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
@ -493,12 +491,6 @@ struct sljit_compiler {
|
|||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
sljit_s32 delay_slot;
|
||||
sljit_s32 cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||
/* Need to allocate register save area to make calls. */
|
||||
sljit_s32 mode;
|
||||
|
@ -702,17 +694,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type);
|
|||
overwrites the previous context.
|
||||
*/
|
||||
|
||||
/* The SLJIT_S0/SLJIT_S1 registers are not saved / restored on function
|
||||
enter / return. Instead, these registers can be used to pass / return
|
||||
data (such as global / local context pointers) across function calls.
|
||||
This is an sljit specific (non ABI compatible) function call extension
|
||||
so both the caller and called function must be compiled by sljit. */
|
||||
#define SLJIT_ENTER_KEEP_S0 0x00000001
|
||||
#define SLJIT_ENTER_KEEP_S0_S1 0x00000002
|
||||
/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive)
|
||||
are not saved / restored on function enter / return. Instead,
|
||||
these registers can be used to pass / return data (such as
|
||||
global / local context pointers) across function calls. The
|
||||
value of n must be between 1 and 3. Furthermore, this option
|
||||
is only supported by register argument calling convention, so
|
||||
SLJIT_ENTER_REG_ARG (see below) must be specified as well. */
|
||||
#define SLJIT_ENTER_KEEP(n) (n)
|
||||
|
||||
/* The compiled function uses cdecl calling
|
||||
* convention instead of SLJIT_FUNC. */
|
||||
#define SLJIT_ENTER_CDECL 0x00000004
|
||||
/* The compiled function uses an sljit specific register argument
|
||||
* calling convention. This is a lightweight function call type where
|
||||
* both the caller and called function must be compiled with sljit.
|
||||
* The jump type of the function call must be SLJIT_CALL_REG_ARG
|
||||
* and the called function must store all arguments in registers. */
|
||||
#define SLJIT_ENTER_REG_ARG 0x00000004
|
||||
|
||||
/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
|
||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
||||
|
@ -819,8 +815,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
|
|||
Write-back is supported except for one instruction: 32 bit signed
|
||||
load with [reg+imm] addressing mode on 64 bit.
|
||||
mips: [reg+imm], -65536 <= imm <= 65535
|
||||
sparc: [reg+imm], -4096 <= imm <= 4095
|
||||
[reg+reg] is supported
|
||||
Write-back is not supported
|
||||
riscv: [reg+imm], -2048 <= imm <= 2047
|
||||
Write-back is not supported
|
||||
s390x: [reg+imm], -2^19 <= imm < 2^19
|
||||
[reg+reg] is supported
|
||||
Write-back is not supported
|
||||
|
@ -1293,11 +1290,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
#define SLJIT_JUMP 34
|
||||
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
|
||||
#define SLJIT_FAST_CALL 35
|
||||
/* Called function must be declared with the SLJIT_FUNC attribute. */
|
||||
/* Default C calling convention. */
|
||||
#define SLJIT_CALL 36
|
||||
/* Called function must be declared with cdecl attribute.
|
||||
This is the default attribute for C functions. */
|
||||
#define SLJIT_CALL_CDECL 37
|
||||
/* Called function must be an sljit compiled function.
|
||||
See SLJIT_ENTER_REG_ARG option. */
|
||||
#define SLJIT_CALL_REG_ARG 37
|
||||
|
||||
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
||||
#define SLJIT_REWRITABLE_JUMP 0x1000
|
||||
|
@ -1305,10 +1302,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
the called function returns to the caller of the current function. The
|
||||
stack usage is reduced before the call, but it is not necessarily reduced
|
||||
to zero. In the latter case the compiler needs to allocate space for some
|
||||
arguments and the return register must be kept as well.
|
||||
|
||||
This feature is highly experimental and not supported on SPARC platform
|
||||
at the moment. */
|
||||
arguments and the return address must be stored on the stack as well. */
|
||||
#define SLJIT_CALL_RETURN 0x2000
|
||||
|
||||
/* Emit a jump instruction. The destination is not set, only the type of the jump.
|
||||
|
@ -1407,32 +1401,58 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
|
||||
/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */
|
||||
|
||||
/* Memory load operation. This is the default. */
|
||||
#define SLJIT_MEM_LOAD 0x000000
|
||||
/* Memory store operation. */
|
||||
#define SLJIT_MEM_STORE 0x000200
|
||||
|
||||
/* Load or stora data from an unaligned address. */
|
||||
#define SLJIT_MEM_UNALIGNED 0x000400
|
||||
/* Load or store data and update the base address with a single operation. */
|
||||
/* Base register is updated before the memory access. */
|
||||
#define SLJIT_MEM_PRE 0x000800
|
||||
/* Base register is updated after the memory access. */
|
||||
#define SLJIT_MEM_POST 0x001000
|
||||
|
||||
/* The following flags are supported when SLJIT_MEM_UNALIGNED is specified: */
|
||||
|
||||
/* Defines 16 bit alignment for unaligned accesses. */
|
||||
#define SLJIT_MEM_ALIGNED_16 0x010000
|
||||
/* Defines 32 bit alignment for unaligned accesses. */
|
||||
#define SLJIT_MEM_ALIGNED_32 0x020000
|
||||
|
||||
/* The following flags are supported when SLJIT_MEM_PRE or
|
||||
SLJIT_MEM_POST is specified: */
|
||||
|
||||
/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
|
||||
Instead the function returns with SLJIT_SUCCESS if the instruction
|
||||
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
|
||||
allows runtime checking of available instruction forms. */
|
||||
#define SLJIT_MEM_SUPP 0x0200
|
||||
/* Memory load operation. This is the default. */
|
||||
#define SLJIT_MEM_LOAD 0x0000
|
||||
/* Memory store operation. */
|
||||
#define SLJIT_MEM_STORE 0x0400
|
||||
/* Base register is updated before the memory access. */
|
||||
#define SLJIT_MEM_PRE 0x0800
|
||||
/* Base register is updated after the memory access. */
|
||||
#define SLJIT_MEM_POST 0x1000
|
||||
#define SLJIT_MEM_SUPP 0x010000
|
||||
|
||||
/* Emit a single memory load or store with update instruction. When the
|
||||
requested instruction form is not supported by the CPU, it returns
|
||||
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
|
||||
allows specializing tight loops based on the supported instruction
|
||||
forms (see SLJIT_MEM_SUPP flag).
|
||||
/* The sljit_emit_mem emits instructions for various memory operations:
|
||||
|
||||
When SLJIT_MEM_UNALIGNED is set in type argument:
|
||||
Emit instructions for unaligned memory loads or stores. When
|
||||
SLJIT_UNALIGNED is not defined, the only way to access unaligned
|
||||
memory data is using sljit_emit_mem. Otherwise all operations (e.g.
|
||||
sljit_emit_op1/2, or sljit_emit_fop1/2) supports unaligned access.
|
||||
In general, the performance of unaligned memory accesses are often
|
||||
lower than aligned and should be avoided.
|
||||
|
||||
When SLJIT_MEM_PRE or SLJIT_MEM_POST is set in type argument:
|
||||
Emit a single memory load or store with update instruction.
|
||||
When the requested instruction form is not supported by the CPU,
|
||||
it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the
|
||||
instruction. This allows specializing tight loops based on
|
||||
the supported instruction forms (see SLJIT_MEM_SUPP flag).
|
||||
|
||||
type must be between SLJIT_MOV and SLJIT_MOV_P and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
combined with SLJIT_MEM_* flags.
|
||||
reg is the source or destination register, and must be
|
||||
different from the base register of the mem operand
|
||||
mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand
|
||||
when SLJIT_MEM_PRE or SLJIT_MEM_POST is passed
|
||||
mem must be a memory operand
|
||||
|
||||
Flags: - (does not modify flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
|
@ -1442,9 +1462,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
/* Same as sljit_emit_mem except the followings:
|
||||
|
||||
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
freg is the source or destination floating point register */
|
||||
combined with SLJIT_MEM_* flags.
|
||||
freg is the source or destination floating point register
|
||||
mem must be a memory operand
|
||||
|
||||
Flags: - (does not modify flags) */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
|
@ -1603,7 +1625,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg);
|
|||
/* The following function is a helper function for sljit_emit_op_custom.
|
||||
It returns with the real machine register index of any SLJIT_FLOAT register.
|
||||
|
||||
Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */
|
||||
Note: the index is always an even number on ARM-32, MIPS. */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg);
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|||
#define CMP 0xe1400000
|
||||
#define BKPT 0xe1200070
|
||||
#define EOR 0xe0200000
|
||||
#define LDR 0xe5100000
|
||||
#define MOV 0xe1a00000
|
||||
#define MUL 0xe0000090
|
||||
#define MVN 0xe1e00000
|
||||
|
@ -111,6 +112,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
|||
#define RSC 0xe0e00000
|
||||
#define SBC 0xe0c00000
|
||||
#define SMULL 0xe0c00090
|
||||
#define STR 0xe5000000
|
||||
#define SUB 0xe0400000
|
||||
#define TST 0xe1000000
|
||||
#define UMULL 0xe0800090
|
||||
|
@ -1104,8 +1106,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
local_size = ((size + local_size + 0x7) & ~0x7) - size;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
arg_types = 0;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
word_arg_count = 0;
|
||||
saved_arg_count = 0;
|
||||
#ifdef __SOFTFP__
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
|
||||
|
||||
|
@ -1148,8 +1154,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
if (offset < 4 * sizeof(sljit_sw))
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
|
||||
| RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1310,8 +1315,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
|
|||
lr_dst = SLJIT_FIRST_SAVED_REG;
|
||||
}
|
||||
|
||||
return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
|
||||
| RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
|
||||
return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
|
||||
}
|
||||
|
||||
if (local_size > 0)
|
||||
|
@ -1678,23 +1682,17 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
||||
{
|
||||
sljit_uw imm, offset_reg;
|
||||
sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
|
||||
sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff;
|
||||
|
||||
SLJIT_ASSERT (arg & SLJIT_MEM);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask));
|
||||
|
||||
if (!(arg & REG_MASK)) {
|
||||
if (is_type1_transfer) {
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));
|
||||
argw &= 0xfff;
|
||||
}
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));
|
||||
argw &= 0xff;
|
||||
}
|
||||
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)(argw & ~mask)));
|
||||
argw &= mask;
|
||||
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,
|
||||
is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
|
||||
(mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw));
|
||||
}
|
||||
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
|
@ -1702,72 +1700,53 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
arg &= REG_MASK;
|
||||
argw &= 0x3;
|
||||
|
||||
if (argw != 0 && !is_type1_transfer) {
|
||||
if (argw != 0 && (mask == 0xff)) {
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7)));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
|
||||
}
|
||||
|
||||
/* Bit 25: RM is offset. */
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
||||
RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7)));
|
||||
RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_uw)argw << 7)));
|
||||
}
|
||||
|
||||
arg &= REG_MASK;
|
||||
|
||||
if (is_type1_transfer) {
|
||||
if (argw > 0xfff) {
|
||||
imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = argw & 0xfff;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
if (argw > mask) {
|
||||
imm = get_imm((sljit_uw)(argw & ~mask));
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = argw & mask;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
else if (argw < -0xfff) {
|
||||
imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = -(-argw & 0xfff);
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
if (argw >= 0 && argw <= 0xfff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
|
||||
|
||||
if (argw < 0 && argw >= -0xfff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));
|
||||
}
|
||||
else {
|
||||
if (argw > 0xff) {
|
||||
imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff);
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = argw & 0xff;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
else if (argw < -mask) {
|
||||
imm = get_imm((sljit_uw)(-argw & ~mask));
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = -(-argw & mask);
|
||||
arg = tmp_reg;
|
||||
}
|
||||
else if (argw < -0xff) {
|
||||
imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
|
||||
if (imm) {
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = -(-argw & 0xff);
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
if (argw <= mask && argw >= -mask) {
|
||||
if (argw >= 0) {
|
||||
if (mask == 0xff)
|
||||
argw = TYPE2_TRANSFER_IMM(argw);
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
|
||||
}
|
||||
|
||||
if (argw >= 0 && argw <= 0xff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
argw = -argw;
|
||||
|
||||
if (argw < 0 && argw >= -0xff) {
|
||||
argw = -argw;
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
}
|
||||
if (mask == 0xff)
|
||||
argw = TYPE2_TRANSFER_IMM(argw);
|
||||
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw));
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
||||
RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
|
||||
RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25))));
|
||||
}
|
||||
|
||||
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
|
||||
|
@ -1965,15 +1944,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
|||
saved_reg_list[saved_reg_count++] = 1;
|
||||
|
||||
if (saved_reg_count > 0) {
|
||||
FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8)
|
||||
FAIL_IF(push_inst(compiler, STR | 0x2d0000 | (saved_reg_count >= 3 ? 16 : 8)
|
||||
| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
|
||||
if (saved_reg_count >= 2) {
|
||||
SLJIT_ASSERT(saved_reg_list[1] < 8);
|
||||
FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
|
||||
FAIL_IF(push_inst(compiler, STR | 0x8d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
|
||||
}
|
||||
if (saved_reg_count >= 3) {
|
||||
SLJIT_ASSERT(saved_reg_list[2] < 8);
|
||||
FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
|
||||
FAIL_IF(push_inst(compiler, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1987,13 +1966,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
|||
if (saved_reg_count > 0) {
|
||||
if (saved_reg_count >= 3) {
|
||||
SLJIT_ASSERT(saved_reg_list[2] < 8);
|
||||
FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
|
||||
FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
|
||||
}
|
||||
if (saved_reg_count >= 2) {
|
||||
SLJIT_ASSERT(saved_reg_list[1] < 8);
|
||||
FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
|
||||
FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
|
||||
}
|
||||
return push_inst(compiler, 0xe49d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
|
||||
return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
|
||||
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
@ -2095,10 +2074,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -2374,7 +2350,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#undef FPU_LOAD
|
||||
#undef EMIT_FPU_DATA_TRANSFER
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
@ -2482,7 +2457,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
|||
return 0x50000000;
|
||||
|
||||
default:
|
||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
|
||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
|
||||
return 0xe0000000;
|
||||
}
|
||||
}
|
||||
|
@ -2659,7 +2634,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit
|
|||
}
|
||||
FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
|
||||
} else
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2738,51 +2713,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
|
||||
PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
|
||||
return jump;
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
|
||||
return jump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||
return jump;
|
||||
#else /* !__SOFTFP__ */
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||
return jump;
|
||||
}
|
||||
#endif /* __SOFTFP__ */
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
#ifndef __SOFTFP__
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
#endif /* !__SOFTFP__ */
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
#endif /* __SOFTFP__ */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
|
@ -2848,47 +2820,44 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP;
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
return push_inst(compiler, BX | RM(TMP_REG2));
|
||||
}
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
return push_inst(compiler, BX | RM(TMP_REG2));
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
return softfloat_post_call_with_args(compiler, arg_types);
|
||||
}
|
||||
#endif /* __SOFTFP__ */
|
||||
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
return softfloat_post_call_with_args(compiler, arg_types);
|
||||
#else /* !__SOFTFP__ */
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
#ifndef __SOFTFP__
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
#endif /* !__SOFTFP__ */
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
#endif /* __SOFTFP__ */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
|
@ -2969,6 +2938,231 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);
|
||||
}
|
||||
|
||||
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
|
||||
{
|
||||
sljit_s32 arg = *mem;
|
||||
sljit_sw argw = *memw;
|
||||
sljit_uw imm;
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
sljit_sw mask = max_offset >= 0x100 ? 0xfff : 0xff;
|
||||
#else /* !SLJIT_CONFIG_ARM_V5 */
|
||||
sljit_sw mask = 0xfff;
|
||||
|
||||
SLJIT_ASSERT(max_offset >= 0x100);
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||
|
||||
*mem = TMP_REG1;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
*memw = 0;
|
||||
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 7));
|
||||
}
|
||||
|
||||
arg &= REG_MASK;
|
||||
|
||||
if (arg) {
|
||||
if (argw <= max_offset && argw >= -mask) {
|
||||
*mem = arg;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (argw < 0) {
|
||||
imm = get_imm((sljit_uw)(-argw & ~mask));
|
||||
|
||||
if (imm) {
|
||||
*memw = -(-argw & mask);
|
||||
return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm);
|
||||
}
|
||||
} else if ((argw & mask) <= max_offset) {
|
||||
imm = get_imm((sljit_uw)(argw & ~mask));
|
||||
|
||||
if (imm) {
|
||||
*memw = argw & mask;
|
||||
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
|
||||
}
|
||||
} else {
|
||||
imm = get_imm((sljit_uw)((argw | mask) + 1));
|
||||
|
||||
if (imm) {
|
||||
*memw = (argw & mask) - (mask + 1);
|
||||
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imm = (sljit_uw)(argw & ~mask);
|
||||
|
||||
if ((argw & mask) > max_offset) {
|
||||
imm += (sljit_uw)(mask + 1);
|
||||
*memw = (argw & mask) - (mask + 1);
|
||||
} else
|
||||
*memw = argw & mask;
|
||||
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, imm));
|
||||
|
||||
if (arg == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg));
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
|
||||
static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
sljit_s32 flags;
|
||||
sljit_s32 steps;
|
||||
sljit_uw add, shift;
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
flags = BYTE_SIZE;
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
flags |= LOAD_DATA;
|
||||
if ((type & 0xff) == SLJIT_MOV_S8)
|
||||
flags |= SIGNED;
|
||||
|
||||
return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1);
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 1));
|
||||
flags = BYTE_SIZE;
|
||||
steps = 1;
|
||||
break;
|
||||
|
||||
case SLJIT_MOV_S16:
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 1));
|
||||
flags = BYTE_SIZE | SIGNED;
|
||||
steps = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (type & SLJIT_MEM_ALIGNED_32) {
|
||||
flags = WORD_SIZE;
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
flags |= LOAD_DATA;
|
||||
|
||||
return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1);
|
||||
}
|
||||
|
||||
if (!(type & SLJIT_MEM_ALIGNED_16)) {
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 3));
|
||||
flags = BYTE_SIZE;
|
||||
steps = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 2));
|
||||
|
||||
add = 1;
|
||||
if (memw < 0) {
|
||||
add = 0;
|
||||
memw = -memw;
|
||||
}
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, reg, mem, TYPE2_TRANSFER_IMM(memw))));
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (16 << 7) | (2 << 4)));
|
||||
|
||||
if (!add) {
|
||||
memw -= 2;
|
||||
if (memw <= 0) {
|
||||
memw = -memw;
|
||||
add = 1;
|
||||
}
|
||||
} else
|
||||
memw += 2;
|
||||
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)));
|
||||
}
|
||||
|
||||
if (reg == mem) {
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(mem)));
|
||||
mem = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, reg, mem, TYPE2_TRANSFER_IMM(memw))));
|
||||
|
||||
if (!add) {
|
||||
memw -= 2;
|
||||
if (memw <= 0) {
|
||||
memw = -memw;
|
||||
add = 1;
|
||||
}
|
||||
} else
|
||||
memw += 2;
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))));
|
||||
return push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (16 << 7));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(steps > 0);
|
||||
|
||||
add = 1;
|
||||
if (memw < 0) {
|
||||
add = 0;
|
||||
memw = -memw;
|
||||
}
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, reg, mem, memw)));
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (8 << 7) | (2 << 4)));
|
||||
|
||||
while (1) {
|
||||
if (!add) {
|
||||
memw -= 1;
|
||||
if (memw == 0)
|
||||
add = 1;
|
||||
} else
|
||||
memw += 1;
|
||||
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, TMP_REG2, mem, memw)));
|
||||
|
||||
if (--steps == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(TMP_REG2) | (8 << 7) | (2 << 4)));
|
||||
}
|
||||
}
|
||||
|
||||
if (reg == mem) {
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(mem)));
|
||||
mem = TMP_REG1;
|
||||
}
|
||||
|
||||
shift = 8;
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, reg, mem, memw)));
|
||||
|
||||
do {
|
||||
if (!add) {
|
||||
memw -= 1;
|
||||
if (memw == 0)
|
||||
add = 1;
|
||||
} else
|
||||
memw += 1;
|
||||
|
||||
if (steps > 1) {
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, TMP_REG2, mem, memw)));
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (shift << 7)));
|
||||
shift += 8;
|
||||
}
|
||||
} while (--steps != 0);
|
||||
|
||||
flags |= LOAD_DATA;
|
||||
|
||||
if (flags & SIGNED)
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, memw)));
|
||||
|
||||
return push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (shift << 7));
|
||||
}
|
||||
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
|
@ -2979,6 +3173,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||
|
||||
is_type1_transfer = 1;
|
||||
|
||||
switch (type & 0xff) {
|
||||
|
@ -3074,6 +3271,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
sljit_s32 max_offset;
|
||||
sljit_s32 dst;
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
if (type & SLJIT_MEM_ALIGNED_32)
|
||||
return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
|
||||
|
||||
if (type & SLJIT_32)
|
||||
return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw);
|
||||
|
||||
max_offset = 0xfff - 7;
|
||||
if (type & SLJIT_MEM_ALIGNED_16)
|
||||
max_offset++;
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset));
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
|
||||
return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw + 4);
|
||||
}
|
||||
|
||||
max_offset = (type & SLJIT_32) ? 0xfff - 3 : 0xfff - 7;
|
||||
if (type & SLJIT_MEM_ALIGNED_16)
|
||||
max_offset++;
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset));
|
||||
|
||||
dst = TMP_REG1;
|
||||
|
||||
/* Stack offset adjustment is not needed because dst
|
||||
is not stored on the stack when mem is SLJIT_SP. */
|
||||
|
||||
if (mem == TMP_REG1) {
|
||||
dst = SLJIT_R3;
|
||||
|
||||
if (compiler->scratches >= 4)
|
||||
FAIL_IF(push_inst(compiler, STR | (1 << 21) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8));
|
||||
}
|
||||
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw));
|
||||
FAIL_IF(push_inst(compiler, VMOV | VN(freg) | RD(dst)));
|
||||
|
||||
if (!(type & SLJIT_32)) {
|
||||
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw + 4));
|
||||
FAIL_IF(push_inst(compiler, VMOV | VN(freg) | 0x80 | RD(dst)));
|
||||
}
|
||||
|
||||
if (dst == SLJIT_R3 && compiler->scratches >= 4)
|
||||
FAIL_IF(push_inst(compiler, (LDR ^ (0x1 << 24)) | (0x1 << 23) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8));
|
||||
return SLJIT_SUCCESS;
|
||||
#else /* !SLJIT_CONFIG_ARM_V5 */
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
|
||||
|
||||
if (type & SLJIT_32)
|
||||
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1);
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
|
||||
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
|
||||
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1);
|
||||
}
|
||||
|
||||
if (type & SLJIT_32) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
|
||||
return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2));
|
||||
}
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1));
|
||||
return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1));
|
||||
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||
}
|
||||
|
||||
#undef FPU_LOAD
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
|
|
|
@ -1001,23 +1001,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
if (prev != -1)
|
||||
FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (local_size > 4096)
|
||||
FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
|
||||
#endif /* _WIN32 */
|
||||
|
||||
tmp = SLJIT_R0;
|
||||
while (arg_types > 0) {
|
||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
||||
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp)));
|
||||
saved_arg_count++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
saved_arg_count = 0;
|
||||
tmp = SLJIT_R0;
|
||||
|
||||
while (arg_types) {
|
||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
||||
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
||||
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp)));
|
||||
saved_arg_count++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -1390,10 +1394,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -1833,11 +1834,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
|
@ -1927,11 +1924,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
|
@ -2016,6 +2009,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||
|
||||
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
|
@ -2070,6 +2066,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
|
||||
|
||||
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
|
|
|
@ -890,8 +890,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
#define HALF_SIZE 0x08
|
||||
#define PRELOAD 0x0c
|
||||
|
||||
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
|
||||
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
|
||||
#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))
|
||||
#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))
|
||||
|
||||
/*
|
||||
1st letter:
|
||||
|
@ -993,8 +993,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
sljit_uw tmp;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
|
||||
arg &= ~SLJIT_MEM;
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -0xff && argw <= 0xfff));
|
||||
|
||||
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
||||
|
@ -1012,15 +1011,17 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
other_r = OFFS_REG(arg);
|
||||
arg &= 0xf;
|
||||
arg &= REG_MASK;
|
||||
|
||||
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
|
||||
return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
|
||||
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4));
|
||||
}
|
||||
|
||||
arg &= REG_MASK;
|
||||
|
||||
if (argw > 0xfff) {
|
||||
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
||||
tmp = get_imm((sljit_uw)(argw & ~0xfff));
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
||||
arg = tmp_reg;
|
||||
|
@ -1028,7 +1029,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
}
|
||||
}
|
||||
else if (argw < -0xff) {
|
||||
tmp = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
|
||||
tmp = get_imm((sljit_uw)(-argw & ~0xff));
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
||||
arg = tmp_reg;
|
||||
|
@ -1036,27 +1037,28 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
}
|
||||
}
|
||||
|
||||
/* 16 bit instruction forms. */
|
||||
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
|
||||
tmp = 3;
|
||||
if (IS_WORD_SIZE(flags)) {
|
||||
if (OFFSET_CHECK(0x1f, 2))
|
||||
if (ALIGN_CHECK(argw, 0x1f, 2))
|
||||
tmp = 2;
|
||||
}
|
||||
else if (flags & BYTE_SIZE)
|
||||
{
|
||||
if (OFFSET_CHECK(0x1f, 0))
|
||||
if (ALIGN_CHECK(argw, 0x1f, 0))
|
||||
tmp = 0;
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(flags & HALF_SIZE);
|
||||
if (OFFSET_CHECK(0x1f, 1))
|
||||
if (ALIGN_CHECK(argw, 0x1f, 1))
|
||||
tmp = 1;
|
||||
}
|
||||
|
||||
if (tmp < 3)
|
||||
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));
|
||||
}
|
||||
else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {
|
||||
else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && ALIGN_CHECK(argw, 0xff, 2) && reg_map[reg] <= 7) {
|
||||
/* SP based immediate. */
|
||||
return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));
|
||||
}
|
||||
|
@ -1074,6 +1076,9 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
|
||||
}
|
||||
|
||||
#undef ALIGN_CHECK
|
||||
#undef IS_WORD_SIZE
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Entry, exit */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
@ -1132,8 +1137,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
local_size = ((size + local_size + 0x7) & ~0x7) - size;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
arg_types = 0;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
word_arg_count = 0;
|
||||
saved_arg_count = 0;
|
||||
#ifdef __SOFTFP__
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
|
||||
|
||||
|
@ -1690,10 +1699,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -1960,8 +1966,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
|
|||
return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
|
||||
}
|
||||
|
||||
#undef FPU_LOAD
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Other instructions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
@ -2310,52 +2314,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
|
||||
jump = sljit_emit_jump(compiler, type);
|
||||
PTR_FAIL_IF(jump == NULL);
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
|
||||
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
|
||||
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
|
||||
PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
|
||||
|
||||
PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
|
||||
return jump;
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
|
||||
return jump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||
return jump;
|
||||
#else
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||
return jump;
|
||||
}
|
||||
#endif /* __SOFTFP__ */
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
/* ldmia sp!, {..., lr} */
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
#ifndef __SOFTFP__
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
#endif /* !__SOFTFP__ */
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||
|
@ -2412,48 +2413,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
#ifdef __SOFTFP__
|
||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP;
|
||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||
type = SLJIT_JUMP;
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
|
||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
|
||||
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
|
||||
|
||||
if (extra_space > 0) {
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
|
||||
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
|
||||
FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
|
||||
|
||||
FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
return push_inst16(compiler, BX | RN3(TMP_REG2));
|
||||
}
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
return push_inst16(compiler, BX | RN3(TMP_REG2));
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
return softfloat_post_call_with_args(compiler, arg_types);
|
||||
}
|
||||
#endif /* __SOFTFP__ */
|
||||
|
||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||
return softfloat_post_call_with_args(compiler, arg_types);
|
||||
#else /* !__SOFTFP__ */
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
/* ldmia sp!, {..., lr} */
|
||||
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
#ifndef __SOFTFP__
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||
#endif /* !__SOFTFP__ */
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
#endif /* __SOFTFP__ */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
|
@ -2567,6 +2565,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||
|
||||
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
|
@ -2615,6 +2616,109 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);
|
||||
}
|
||||
|
||||
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
|
||||
{
|
||||
sljit_s32 arg = *mem;
|
||||
sljit_sw argw = *memw;
|
||||
sljit_uw imm;
|
||||
|
||||
*mem = TMP_REG1;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
*memw = 0;
|
||||
return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 6));
|
||||
}
|
||||
|
||||
arg &= REG_MASK;
|
||||
|
||||
if (arg) {
|
||||
if (argw <= max_offset && argw >= -0xff) {
|
||||
*mem = arg;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (argw < 0) {
|
||||
imm = get_imm((sljit_uw)(-argw & ~0xff));
|
||||
|
||||
if (imm) {
|
||||
*memw = -(-argw & 0xff);
|
||||
return push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg) | imm);
|
||||
}
|
||||
} else if ((argw & 0xfff) <= max_offset) {
|
||||
imm = get_imm((sljit_uw)(argw & ~0xfff));
|
||||
|
||||
if (imm) {
|
||||
*memw = argw & 0xfff;
|
||||
return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
|
||||
}
|
||||
} else {
|
||||
imm = get_imm((sljit_uw)((argw | 0xfff) + 1));
|
||||
|
||||
if (imm) {
|
||||
*memw = (argw & 0xfff) - 0x1000;
|
||||
return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imm = (sljit_uw)(argw & ~0xfff);
|
||||
|
||||
if ((argw & 0xfff) > max_offset) {
|
||||
imm += 0x1000;
|
||||
*memw = (argw & 0xfff) - 0x1000;
|
||||
} else
|
||||
*memw = argw & 0xfff;
|
||||
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, imm));
|
||||
|
||||
if (arg == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, arg));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
if (type & SLJIT_MEM_ALIGNED_32)
|
||||
return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | RT4(TMP_REG2)));
|
||||
|
||||
if (type & SLJIT_32)
|
||||
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1);
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1));
|
||||
FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | 0x80 | RT4(TMP_REG2)));
|
||||
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1);
|
||||
}
|
||||
|
||||
if (type & SLJIT_32) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
|
||||
return push_inst32(compiler, VMOV | DN4(freg) | RT4(TMP_REG2));
|
||||
}
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
|
||||
mem |= SLJIT_MEM;
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1));
|
||||
return push_inst32(compiler, VMOV2 | DM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1));
|
||||
}
|
||||
|
||||
#undef FPU_LOAD
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
|
|
|
@ -196,8 +196,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
sljit_s32 arg_types)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_u32 extra_space = (sljit_u32)type;
|
||||
sljit_ins ins;
|
||||
sljit_u32 extra_space = 0;
|
||||
sljit_ins ins = NOP;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
@ -206,12 +206,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
PTR_FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||
extra_space = (sljit_u32)type;
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
||||
} else if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
||||
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
|
||||
jump->flags |= IS_JAL | IS_CALL;
|
||||
jump->flags |= IS_JAL;
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
jump->flags |= IS_CALL;
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
} else
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
|
@ -247,16 +258,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
if (ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
|
||||
}
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (FAST_IS_REG(src))
|
||||
else if (src != PIC_ADDR_REG)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
}
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
||||
|
||||
|
|
|
@ -238,12 +238,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
if (type & SLJIT_CALL_RETURN)
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
|
||||
jump->flags |= IS_MOVABLE;
|
||||
|
||||
if (!(type & SLJIT_CALL_RETURN)) {
|
||||
jump->flags |= IS_JAL | IS_CALL;
|
||||
jump->flags |= IS_JAL;
|
||||
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
jump->flags |= IS_CALL;
|
||||
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
} else
|
||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
||||
|
@ -265,16 +273,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
||||
|
||||
if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
src = PIC_ADDR_REG;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
||||
if (ins != NOP)
|
||||
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
|
||||
}
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
||||
else if (FAST_IS_REG(src))
|
||||
else if (src != PIC_ADDR_REG)
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
|
||||
}
|
||||
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||
|
|
|
@ -212,9 +212,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
|
|||
#define JR (HI(0) | LO(8))
|
||||
#endif /* SLJIT_MIPS_REV >= 6 */
|
||||
#define LD (HI(55))
|
||||
#define LDL (HI(26))
|
||||
#define LDR (HI(27))
|
||||
#define LDC1 (HI(53))
|
||||
#define LUI (HI(15))
|
||||
#define LW (HI(35))
|
||||
#define LWL (HI(34))
|
||||
#define LWR (HI(38))
|
||||
#define LWC1 (HI(49))
|
||||
#define MFC1 (HI(17))
|
||||
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
|
||||
|
@ -242,6 +246,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
|
|||
#define OR (HI(0) | LO(37))
|
||||
#define ORI (HI(13))
|
||||
#define SD (HI(63))
|
||||
#define SDL (HI(44))
|
||||
#define SDR (HI(45))
|
||||
#define SDC1 (HI(61))
|
||||
#define SLT (HI(0) | LO(42))
|
||||
#define SLTI (HI(10))
|
||||
|
@ -256,6 +262,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
|
|||
#define SUB_S (HI(17) | FMT_S | LO(1))
|
||||
#define SUBU (HI(0) | LO(35))
|
||||
#define SW (HI(43))
|
||||
#define SWL (HI(42))
|
||||
#define SWR (HI(46))
|
||||
#define SWC1 (HI(57))
|
||||
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
|
||||
#define XOR (HI(0) | LO(38))
|
||||
|
@ -283,11 +291,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
|
|||
#define ADDU_W ADDU
|
||||
#define ADDIU_W ADDIU
|
||||
#define SLL_W SLL
|
||||
#define SRA_W SRA
|
||||
#define SUBU_W SUBU
|
||||
#else
|
||||
#define ADDU_W DADDU
|
||||
#define ADDIU_W DADDIU
|
||||
#define SLL_W DSLL
|
||||
#define SRA_W DSRA
|
||||
#define SUBU_W DSUBU
|
||||
#endif
|
||||
|
||||
|
@ -371,15 +381,14 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
|
|||
jump->addr -= 2 * sizeof(sljit_ins);
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
|
||||
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
|
||||
jump->flags |= PATCH_B;
|
||||
|
||||
if (!(jump->flags & IS_COND)) {
|
||||
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
|
||||
inst[1] = NOP;
|
||||
/* Keep inst[1] */
|
||||
return inst + 1;
|
||||
}
|
||||
inst[0] ^= invert_branch(jump->flags);
|
||||
|
@ -422,7 +431,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
|
|||
if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
|
||||
inst[1] = NOP;
|
||||
/* Keep inst[1] */
|
||||
return inst + 1;
|
||||
}
|
||||
}
|
||||
|
@ -802,27 +811,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
#endif
|
||||
compiler->local_size = local_size;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
tmp = arg_types >> SLJIT_ARG_SHIFT;
|
||||
arg_count = 0;
|
||||
offset = 0;
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||
tmp = arg_types >> SLJIT_ARG_SHIFT;
|
||||
arg_count = 0;
|
||||
|
||||
while (tmp) {
|
||||
offset = arg_count;
|
||||
if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
|
||||
if ((arg_count & 0x1) != 0)
|
||||
while (tmp) {
|
||||
offset = arg_count;
|
||||
if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
|
||||
if ((arg_count & 0x1) != 0)
|
||||
arg_count++;
|
||||
arg_count++;
|
||||
}
|
||||
|
||||
arg_count++;
|
||||
tmp >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
arg_count++;
|
||||
tmp >>= SLJIT_ARG_SHIFT;
|
||||
compiler->args_size = (sljit_uw)arg_count << 2;
|
||||
offset = (offset >= 4) ? (offset << 2) : 0;
|
||||
}
|
||||
|
||||
compiler->args_size = (sljit_uw)arg_count << 2;
|
||||
offset = (offset >= 4) ? (offset << 2) : 0;
|
||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
||||
offset = 0;
|
||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||
|
||||
if (local_size + offset <= -SIMM_MIN) {
|
||||
|
@ -831,9 +840,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
base = S(SLJIT_SP);
|
||||
offset = local_size - SSIZE_OF(sw);
|
||||
} else {
|
||||
FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
|
||||
FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
|
||||
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
|
||||
base = S(TMP_REG2);
|
||||
offset = -SSIZE_OF(sw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
@ -871,6 +880,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
|
||||
}
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
arg_count = 0;
|
||||
word_arg_count = 0;
|
||||
|
@ -1305,8 +1317,6 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
|
||||
}
|
||||
|
||||
#undef TO_ARGW_HI
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
|
||||
{
|
||||
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
|
||||
|
@ -2170,10 +2180,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -2254,8 +2261,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
|
|||
|
||||
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
|
||||
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
|
||||
if (FAST_IS_REG(dst)) {
|
||||
FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Store the integer value from a VFP register. */
|
||||
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
|
||||
|
@ -2277,9 +2289,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
|||
|
||||
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (FAST_IS_REG(src))
|
||||
if (FAST_IS_REG(src)) {
|
||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
else if (src & SLJIT_MEM) {
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
} else if (src & SLJIT_MEM) {
|
||||
/* Load the integer value into a VFP register. */
|
||||
FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
|
||||
}
|
||||
|
@ -2290,6 +2305,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
|
|||
#endif
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
|
||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
|
||||
|
@ -3050,6 +3068,265 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
#endif /* SLJIT_MIPS_REV >= 1 */
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
|
||||
|
||||
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
|
||||
{
|
||||
sljit_s32 arg = *mem;
|
||||
sljit_sw argw = *memw;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
|
||||
if (SLJIT_UNLIKELY(argw)) {
|
||||
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
} else
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
|
||||
*mem = TMP_REG1;
|
||||
*memw = 0;
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (argw <= max_offset && argw >= SIMM_MIN) {
|
||||
*mem = arg & REG_MASK;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
*mem = TMP_REG1;
|
||||
|
||||
if ((sljit_s16)argw > max_offset) {
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
|
||||
*memw = 0;
|
||||
} else {
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
|
||||
*memw = (sljit_s16)argw;
|
||||
}
|
||||
|
||||
if ((arg & REG_MASK) == 0)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1));
|
||||
}
|
||||
|
||||
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
|
||||
#define MEM16_IMM_FIRST(memw) IMM((memw) + 1)
|
||||
#define MEM16_IMM_SECOND(memw) IMM(memw)
|
||||
#define MEMF64_FS_FIRST(freg) FS(freg)
|
||||
#define MEMF64_FS_SECOND(freg) (FS(freg) | ((sljit_ins)1 << 11))
|
||||
#else /* !SLJIT_LITTLE_ENDIAN */
|
||||
#define MEM16_IMM_FIRST(memw) IMM(memw)
|
||||
#define MEM16_IMM_SECOND(memw) IMM((memw) + 1)
|
||||
#define MEMF64_FS_FIRST(freg) (FS(freg) | ((sljit_ins)1 << 11))
|
||||
#define MEMF64_FS_SECOND(freg) FS(freg)
|
||||
#endif /* SLJIT_LITTLE_ENDIAN */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
sljit_s32 op = type & 0xff;
|
||||
sljit_s32 flags = 0;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
flags = BYTE_DATA;
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
flags |= LOAD_DATA;
|
||||
|
||||
if (op == SLJIT_MOV_S8)
|
||||
flags |= SIGNED_DATA;
|
||||
|
||||
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
|
||||
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), MOVABLE_INS));
|
||||
return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), MOVABLE_INS);
|
||||
}
|
||||
|
||||
flags = BYTE_DATA | LOAD_DATA;
|
||||
|
||||
if (op == SLJIT_MOV_S16)
|
||||
flags |= SIGNED_DATA;
|
||||
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), DR(reg)));
|
||||
FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
|
||||
return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
|
||||
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
if (type & SLJIT_MEM_ALIGNED_32) {
|
||||
flags = WORD_DATA;
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
flags |= LOAD_DATA;
|
||||
|
||||
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
|
||||
}
|
||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
|
||||
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
|
||||
return push_inst(compiler, SDR | S(mem) | T(reg) | IMM(memw + 7), MOVABLE_INS);
|
||||
}
|
||||
|
||||
if (mem == reg) {
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
mem = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM(memw), DR(reg)));
|
||||
return push_inst(compiler, LDR | S(mem) | T(reg) | IMM(memw + 7), DR(reg));
|
||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||
}
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
|
||||
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
|
||||
return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
if (mem == reg) {
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
mem = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
|
||||
return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg));
|
||||
|
||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
||||
if (mem == reg) {
|
||||
FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
mem = TMP_REG1;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
|
||||
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)));
|
||||
|
||||
if (op == SLJIT_MOV_U32) {
|
||||
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
|
||||
return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg));
|
||||
#else /* SLJIT_MIPS_REV < 1 */
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
|
||||
return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
|
||||
#endif /* SLJIT_MIPS_REV >= 2 */
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
|
||||
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
|
||||
|
||||
if (type & SLJIT_MEM_STORE) {
|
||||
if (type & SLJIT_32) {
|
||||
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
|
||||
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), DR(TMP_REG2)));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS));
|
||||
|
||||
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), DR(TMP_REG2)));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), MOVABLE_INS));
|
||||
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
|
||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
||||
FAIL_IF(push_inst(compiler, MFC1 | (1 << 21) | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
|
||||
return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
|
||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||
}
|
||||
|
||||
if (type & SLJIT_32) {
|
||||
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), MOVABLE_INS));
|
||||
|
||||
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), MOVABLE_INS));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
||||
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
|
||||
FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
|
||||
|
||||
FAIL_IF(push_inst(compiler, MTC1 | (1 << 21) | T(TMP_REG2) | FS(freg), MOVABLE_INS));
|
||||
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#undef MEM16_IMM_FIRST
|
||||
#undef MEM16_IMM_SECOND
|
||||
#undef MEMF64_FS_FIRST
|
||||
#undef MEMF64_FS_SECOND
|
||||
|
||||
#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
|
||||
|
||||
#undef TO_ARGW_HI
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||
{
|
||||
struct sljit_const *const_;
|
||||
|
|
|
@ -735,8 +735,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1)
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
|
||||
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
|
||||
|
||||
if (!(options & SLJIT_ENTER_REG_ARG))
|
||||
local_size += SSIZE_OF(sw);
|
||||
|
||||
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
||||
compiler->local_size = local_size;
|
||||
|
||||
|
@ -775,8 +779,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
|
||||
}
|
||||
|
||||
offset -= SSIZE_OF(sw);
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||
offset -= SSIZE_OF(sw);
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||
}
|
||||
|
||||
tmp = SLJIT_S0 - saveds;
|
||||
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
|
||||
|
@ -790,9 +796,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
saved_arg_count = 0;
|
||||
|
||||
while (arg_types > 0) {
|
||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
||||
|
@ -834,13 +845,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
|
|||
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1)
|
||||
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
|
||||
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
|
||||
|
||||
if (!(options & SLJIT_ENTER_REG_ARG))
|
||||
local_size += SSIZE_OF(sw);
|
||||
|
||||
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
|
||||
{
|
||||
sljit_s32 i, tmp, base, offset;
|
||||
|
@ -872,8 +886,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
|
|||
FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
|
||||
}
|
||||
|
||||
offset -= SSIZE_OF(sw);
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||
if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
|
||||
offset -= SSIZE_OF(sw);
|
||||
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||
}
|
||||
|
||||
tmp = SLJIT_S0 - compiler->saveds;
|
||||
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
|
||||
|
@ -1631,7 +1647,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||
}
|
||||
}
|
||||
if (GET_OPCODE(op) != SLJIT_AND) {
|
||||
if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
|
||||
/* Unlike or and xor, the and resets unwanted bits as well. */
|
||||
if (TEST_UI_IMM(src2, src2w)) {
|
||||
compiler->imm = (sljit_ins)src2w;
|
||||
|
@ -1668,10 +1684,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -2139,7 +2152,7 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type
|
|||
return (4 << 21) | ((4 + 3) << 16);
|
||||
|
||||
default:
|
||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
|
||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
|
||||
return (20 << 21);
|
||||
}
|
||||
}
|
||||
|
@ -2186,7 +2199,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||
#endif
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
|
@ -2194,11 +2208,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
|
@ -2272,14 +2282,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
|
@ -2429,10 +2436,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
|
||||
return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
|
||||
|
@ -2458,6 +2463,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||
|
||||
if (type & SLJIT_MEM_POST)
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
|
@ -2554,6 +2562,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
if (type & SLJIT_MEM_UNALIGNED)
|
||||
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
|
||||
|
||||
if (type & SLJIT_MEM_POST)
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
|
|
|
@ -665,7 +665,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
else if (local_size > 0)
|
||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
saved_arg_count = 0;
|
||||
tmp = SLJIT_R0;
|
||||
|
||||
while (arg_types > 0) {
|
||||
|
@ -1727,10 +1731,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -2199,11 +2200,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
|
@ -2368,11 +2365,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
|
|
|
@ -1729,7 +1729,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
|
||||
FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
saved_arg_count = 0;
|
||||
tmp = 0;
|
||||
while (arg_types > 0) {
|
||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
||||
|
@ -2800,10 +2804,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -3192,11 +3193,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
|
@ -3248,11 +3245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm)
|
||||
{
|
||||
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst)));
|
||||
return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_u32 flags,
|
||||
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
|
||||
{
|
||||
SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
|
||||
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOV_S8:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_U8)
|
||||
return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
|
||||
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
|
||||
}
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOV_S16:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
|
||||
return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
|
||||
}
|
||||
SLJIT_ASSERT(dst == src2);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
||||
|
||||
/* Loop. */
|
||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
||||
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | ((sljit_ins)-2 & DISP_MASK), UNMOVABLE_INS));
|
||||
return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
|
||||
|
||||
case SLJIT_ADD:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
|
||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_ADDC:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
|
||||
return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_SUB:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
|
||||
return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_SUBC:
|
||||
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
|
||||
return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_MUL:
|
||||
compiler->status_flags_state = 0;
|
||||
FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
if (!(flags & SET_FLAGS))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK)));
|
||||
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);
|
||||
|
||||
case SLJIT_AND:
|
||||
return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_OR:
|
||||
return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_XOR:
|
||||
return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
|
||||
|
||||
case SLJIT_SHL:
|
||||
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_LSHR:
|
||||
FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
|
||||
case SLJIT_ASHR:
|
||||
FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
|
||||
return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS);
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
|
||||
{
|
||||
sljit_s32 reg_index = 8;
|
||||
sljit_s32 word_reg_index = 8;
|
||||
sljit_s32 float_arg_index = 1;
|
||||
sljit_s32 double_arg_count = 0;
|
||||
sljit_u32 float_offset = (16 + 6) * sizeof(sljit_sw);
|
||||
sljit_s32 types = 0;
|
||||
sljit_s32 reg = 0;
|
||||
sljit_s32 move_to_tmp2 = 0;
|
||||
|
||||
if (src)
|
||||
reg = reg_map[*src & REG_MASK];
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
|
||||
while (arg_types) {
|
||||
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
|
||||
|
||||
switch (arg_types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_index++;
|
||||
double_arg_count++;
|
||||
if (reg_index == reg || reg_index + 1 == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index += 2;
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_index++;
|
||||
if (reg_index == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index++;
|
||||
break;
|
||||
default:
|
||||
if (reg_index != word_reg_index && reg_index == reg)
|
||||
move_to_tmp2 = 1;
|
||||
reg_index++;
|
||||
word_reg_index++;
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
if (move_to_tmp2) {
|
||||
if (reg < 14)
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));
|
||||
*src = TMP_REG1;
|
||||
}
|
||||
|
||||
arg_types = types;
|
||||
|
||||
while (arg_types) {
|
||||
switch (arg_types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
float_arg_index--;
|
||||
if (float_arg_index == 4 && double_arg_count == 4) {
|
||||
/* The address is not doubleword aligned, so two instructions are required to store the double. */
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
float_arg_index--;
|
||||
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
arg_types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
float_offset = (16 + 6) * sizeof(sljit_sw);
|
||||
|
||||
while (types) {
|
||||
switch (types & SLJIT_ARG_MASK) {
|
||||
case SLJIT_ARG_TYPE_F64:
|
||||
reg_index -= 2;
|
||||
if (reg_index < 14) {
|
||||
if ((reg_index & 0x1) != 0) {
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
if (reg_index < 8 + 6 - 1)
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1));
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
}
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
case SLJIT_ARG_TYPE_F32:
|
||||
reg_index--;
|
||||
if (reg_index < 8 + 6)
|
||||
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
|
||||
float_offset -= sizeof(sljit_f64);
|
||||
break;
|
||||
default:
|
||||
reg_index--;
|
||||
word_reg_index--;
|
||||
|
||||
if (reg_index != word_reg_index) {
|
||||
if (reg_index < 14)
|
||||
FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
types >>= SLJIT_ARG_SHIFT;
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst)));
|
||||
return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins *)addr;
|
||||
SLJIT_UNUSED_ARG(executable_offset);
|
||||
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
|
||||
SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000));
|
||||
inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff);
|
||||
inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff);
|
||||
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
|
||||
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 2);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
|
||||
{
|
||||
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -101,34 +101,38 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
|||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if (!(b & OFFS_REG_MASK)) {
|
||||
if (NOT_HALFWORD(immb)) {
|
||||
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG2);
|
||||
else
|
||||
b |= TMP_REG2;
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 4)
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
|
||||
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
|
||||
immb = 0;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG2);
|
||||
else
|
||||
b |= TMP_REG2;
|
||||
}
|
||||
|
||||
if (!(b & REG_MASK))
|
||||
inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
|
||||
if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
|
||||
if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_s8);
|
||||
else
|
||||
inst_size += sizeof(sljit_s32);
|
||||
}
|
||||
else if (reg_lmap[b & REG_MASK] == 5)
|
||||
inst_size += sizeof(sljit_s8);
|
||||
else if (reg_lmap[b & REG_MASK] == 5) {
|
||||
/* Swap registers if possible. */
|
||||
if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5)
|
||||
b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
|
||||
else
|
||||
inst_size += sizeof(sljit_s8);
|
||||
}
|
||||
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
|
||||
if (reg_lmap[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_SP);
|
||||
|
||||
if (b & OFFS_REG_MASK) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
|
@ -223,7 +227,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
|||
} else if (b & REG_MASK) {
|
||||
reg_lmap_b = reg_lmap[b & REG_MASK];
|
||||
|
||||
if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_lmap_b == 5) {
|
||||
if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
|
||||
if (immb != 0 || reg_lmap_b == 5) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
|
@ -248,8 +252,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (reg_lmap_b == 5)
|
||||
*buf_ptr |= 0x40;
|
||||
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
|
||||
|
||||
if (reg_lmap_b == 5)
|
||||
*buf_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -379,6 +389,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
|||
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
|
||||
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
|
||||
|
||||
if (options & SLJIT_ENTER_REG_ARG)
|
||||
arg_types = 0;
|
||||
|
||||
/* Emit ENDBR64 at function entry if needed. */
|
||||
FAIL_IF(emit_endbranch(compiler));
|
||||
|
||||
|
@ -786,17 +799,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
|||
|
||||
compiler->mode32 = 0;
|
||||
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||
|
||||
if (type & SLJIT_CALL_RETURN) {
|
||||
PTR_FAIL_IF(emit_stack_frame_release(compiler));
|
||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
|
@ -822,16 +833,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
FAIL_IF(emit_stack_frame_release(compiler));
|
||||
type = SLJIT_JUMP;
|
||||
}
|
||||
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
if (type & SLJIT_CALL_RETURN)
|
||||
type = SLJIT_JUMP;
|
||||
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,7 @@
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
||||
{
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
return "x86" SLJIT_CPUINFO " ABI:fastcall";
|
||||
#else
|
||||
return "x86" SLJIT_CPUINFO;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -79,9 +75,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
|
|||
#define CHECK_EXTRA_REGS(p, w, do) \
|
||||
if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
|
||||
if (p <= compiler->scratches) \
|
||||
w = compiler->scratches_offset + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
|
||||
w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
|
||||
else \
|
||||
w = compiler->locals_offset + ((p) - SLJIT_S2) * SSIZE_OF(sw); \
|
||||
w = SLJIT_LOCALS_OFFSET_BASE + ((p) - SLJIT_S2) * SSIZE_OF(sw); \
|
||||
p = SLJIT_MEM1(SLJIT_SP); \
|
||||
do; \
|
||||
}
|
||||
|
@ -2338,10 +2334,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
|||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||
|
||||
if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
|
@ -2851,10 +2844,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||
}
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
||||
|
||||
#else
|
||||
|
@ -2965,10 +2955,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
if (GET_OPCODE(op) < SLJIT_ADD)
|
||||
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
compiler->skip_checks = 1;
|
||||
#endif
|
||||
SLJIT_SKIP_CHECKS(compiler);
|
||||
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
||||
#endif /* SLJIT_CONFIG_X86_64 */
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue