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 file ChangeLog history information documenting your changes. Please read
|
||||||
the FAQ for more information on the distribution of modified source versions.
|
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;
|
static constexpr bool Recompiler = !Interpreter;
|
||||||
|
|
||||||
//VU instructions
|
//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;
|
static constexpr bool SIMD = !SISD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,27 +25,32 @@ auto AI::unload() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AI::main() -> void {
|
auto AI::main() -> void {
|
||||||
sample();
|
f64 left = 0, right = 0;
|
||||||
|
sample(left, right);
|
||||||
|
stream->frame(left, right);
|
||||||
step(dac.period);
|
step(dac.period);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AI::sample() -> void {
|
auto AI::sample(f64& left, f64& right) -> void {
|
||||||
if(io.dmaCount == 0) return stream->frame(0.0, 0.0);
|
if(io.dmaCount == 0) return;
|
||||||
|
|
||||||
|
if(io.dmaLength[0] && io.dmaEnable) {
|
||||||
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
|
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
|
||||||
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
|
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
|
||||||
auto left = s16(data >> 16);
|
auto l = s16(data >> 16);
|
||||||
auto right = s16(data >> 0);
|
auto r = s16(data >> 0);
|
||||||
stream->frame(left / 32768.0, right / 32768.0);
|
left = l / 32768.0;
|
||||||
|
right = r / 32768.0;
|
||||||
|
|
||||||
io.dmaAddress[0].bit(0,12) += 4;
|
io.dmaAddress[0].bit(0,12) += 4;
|
||||||
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
|
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
|
||||||
io.dmaLength[0] -= 4;
|
io.dmaLength[0] -= 4;
|
||||||
|
}
|
||||||
if(!io.dmaLength[0]) {
|
if(!io.dmaLength[0]) {
|
||||||
mi.raise(MI::IRQ::AI);
|
|
||||||
if(--io.dmaCount) {
|
if(--io.dmaCount) {
|
||||||
io.dmaAddress[0] = io.dmaAddress[1];
|
io.dmaAddress[0] = io.dmaAddress[1];
|
||||||
io.dmaLength [0] = io.dmaLength [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 load(Node::Object) -> void;
|
||||||
auto unload() -> void;
|
auto unload() -> void;
|
||||||
auto main() -> void;
|
auto main() -> void;
|
||||||
auto sample() -> void;
|
auto sample(f64& left, f64& right) -> void;
|
||||||
auto step(u32 clocks) -> void;
|
auto step(u32 clocks) -> void;
|
||||||
auto power(bool reset) -> void;
|
auto power(bool reset) -> void;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ auto AI::readWord(u32 address) -> u32 {
|
||||||
data.bit( 0) = io.dmaCount > 1;
|
data.bit( 0) = io.dmaCount > 1;
|
||||||
data.bit(20) = 1;
|
data.bit(20) = 1;
|
||||||
data.bit(24) = 1;
|
data.bit(24) = 1;
|
||||||
|
data.bit(25) = io.dmaEnable;
|
||||||
data.bit(30) = io.dmaCount > 0;
|
data.bit(30) = io.dmaCount > 0;
|
||||||
data.bit(31) = io.dmaCount > 1;
|
data.bit(31) = io.dmaCount > 1;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +35,8 @@ auto AI::writeWord(u32 address, u32 data_) -> void {
|
||||||
if(address == 1) {
|
if(address == 1) {
|
||||||
//AI_LENGTH
|
//AI_LENGTH
|
||||||
n18 length = data.bit(0,17) & ~7;
|
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.dmaLength[io.dmaCount] = length;
|
||||||
io.dmaCount++;
|
io.dmaCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace ares::Nintendo64 {
|
||||||
|
|
||||||
CPU cpu;
|
CPU cpu;
|
||||||
#include "context.cpp"
|
#include "context.cpp"
|
||||||
#include "icache.cpp"
|
|
||||||
#include "dcache.cpp"
|
#include "dcache.cpp"
|
||||||
#include "tlb.cpp"
|
#include "tlb.cpp"
|
||||||
#include "memory.cpp"
|
#include "memory.cpp"
|
||||||
|
|
|
@ -103,26 +103,80 @@ struct CPU : Thread {
|
||||||
|
|
||||||
//icache.cpp
|
//icache.cpp
|
||||||
struct InstructionCache {
|
struct InstructionCache {
|
||||||
|
CPU& self;
|
||||||
struct Line;
|
struct Line;
|
||||||
auto line(u32 address) -> Line&;
|
auto line(u32 address) -> Line& { return lines[address >> 5 & 0x1ff]; }
|
||||||
auto step(u32 address) -> void;
|
|
||||||
auto fetch(u32 address) -> u32;
|
//used by the recompiler to simulate instruction cache fetch timing
|
||||||
auto read(u32 address) -> u32;
|
auto step(u32 address) -> void {
|
||||||
auto power(bool reset) -> 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
|
//16KB
|
||||||
struct Line {
|
struct Line {
|
||||||
auto hit(u32 address) const -> bool;
|
auto hit(u32 address) const -> bool { return valid && tag == (address & ~0x0000'0fff); }
|
||||||
auto fill(u32 address) -> void;
|
auto fill(u32 address, CPU& cpu) -> void {
|
||||||
auto writeBack() -> void;
|
cpu.step(48);
|
||||||
auto read(u32 address) const -> u32;
|
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;
|
bool valid;
|
||||||
u32 tag;
|
u32 tag;
|
||||||
u16 index;
|
u16 index;
|
||||||
u32 words[8];
|
u32 words[8];
|
||||||
} lines[512];
|
} lines[512];
|
||||||
} icache;
|
} icache{*this};
|
||||||
|
|
||||||
//dcache.cpp
|
//dcache.cpp
|
||||||
struct DataCache {
|
struct DataCache {
|
||||||
|
@ -705,12 +759,31 @@ struct CPU : Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto invalidate(u32 address) -> void {
|
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;
|
pools[address >> 8 & 0x1fffff] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto invalidateRange(u32 address, u32 length) -> void {
|
auto invalidateRange(u32 address, u32 length) -> void {
|
||||||
for (u32 s = 0; s < length; s += 256)
|
for (u32 s = 0; s < length; s += 256)
|
||||||
invalidate(address + s);
|
invalidatePool(address + s);
|
||||||
invalidate(address + length - 1);
|
invalidatePool(address + length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pool(u32 address) -> Pool*;
|
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
|
case 0x14: { //icache fill
|
||||||
auto& line = icache.line(address);
|
auto& line = icache.line(address);
|
||||||
line.fill(address);
|
line.fill(address, cpu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x18: { //icache hit write back
|
case 0x18: { //icache hit write back
|
||||||
auto& line = icache.line(address);
|
auto& line = icache.line(address);
|
||||||
if(line.hit(address)) line.writeBack();
|
if(line.hit(address)) line.writeBack(cpu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
|
||||||
return 0; //nop
|
return 0; //nop
|
||||||
case Context::Segment::Mapped:
|
case Context::Segment::Mapped:
|
||||||
if(auto match = tlb.load(vaddr)) {
|
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);
|
step(1);
|
||||||
return bus.read<Word>(match.address & context.physMask);
|
return bus.read<Word>(match.address & context.physMask);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
|
||||||
addressException(vaddr);
|
addressException(vaddr);
|
||||||
return 0; //nop
|
return 0; //nop
|
||||||
case Context::Segment::Cached:
|
case Context::Segment::Cached:
|
||||||
return icache.fetch(vaddr & context.physMask);
|
return icache.fetch(vaddr & context.physMask, cpu);
|
||||||
case Context::Segment::Direct:
|
case Context::Segment::Direct:
|
||||||
step(1);
|
step(1);
|
||||||
return bus.read<Word>(vaddr & context.physMask);
|
return bus.read<Word>(vaddr & context.physMask);
|
||||||
|
|
|
@ -115,6 +115,7 @@ auto CPU::serialize(serializer& s) -> void {
|
||||||
s(scc.tagLo.primaryCacheState);
|
s(scc.tagLo.primaryCacheState);
|
||||||
s(scc.tagLo.physicalAddress);
|
s(scc.tagLo.physicalAddress);
|
||||||
s(scc.epcError);
|
s(scc.epcError);
|
||||||
|
s(scc.latch);
|
||||||
|
|
||||||
for(auto& r : fpu.r) s(r.u64);
|
for(auto& r : fpu.r) s(r.u64);
|
||||||
s(fpu.csr.roundMode);
|
s(fpu.csr.roundMode);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
//started: 2020-04-28
|
//started: 2020-04-28
|
||||||
|
|
||||||
|
#define XXH_INLINE_ALL
|
||||||
|
#include <xxhash.h>
|
||||||
#include <ares/ares.hpp>
|
#include <ares/ares.hpp>
|
||||||
#include <nall/hashset.hpp>
|
#include <nall/hashset.hpp>
|
||||||
#include <nall/recompiler/generic/generic.hpp>
|
#include <nall/recompiler/generic/generic.hpp>
|
||||||
|
@ -9,6 +11,9 @@
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
#if defined(ARCHITECTURE_AMD64)
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
using v128 = __m128i;
|
using v128 = __m128i;
|
||||||
|
#elif defined(ARCHITECTURE_ARM64)
|
||||||
|
#include <sse2neon.h>
|
||||||
|
using v128 = __m128i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(VULKAN)
|
#if defined(VULKAN)
|
||||||
|
|
|
@ -37,7 +37,7 @@ auto PI::dmaWrite() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::CPU::Recompiler) {
|
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++)
|
for (u32 i = 0; i < cur_len; i++)
|
||||||
rdram.ram.write<Byte>(io.dramAddress++, mem[i]);
|
rdram.ram.write<Byte>(io.dramAddress++, mem[i]);
|
||||||
|
|
|
@ -50,9 +50,7 @@ auto RDP::render() -> void {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ANGRYLION_RDP)
|
#if defined(ANGRYLION_RDP)
|
||||||
if (angrylion::ProcessRDPList()) {
|
command.current = angrylion::ProcessRDPList();
|
||||||
command.start = command.current = command.end;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@ auto RDP::serialize(serializer& s) -> void {
|
||||||
s(command.source);
|
s(command.source);
|
||||||
s(command.freeze);
|
s(command.freeze);
|
||||||
s(command.flush);
|
s(command.flush);
|
||||||
|
s(command.startValid);
|
||||||
|
s(command.endValid);
|
||||||
|
s(command.startGclk);
|
||||||
s(command.ready);
|
s(command.ready);
|
||||||
|
|
||||||
s(io.bist.check);
|
s(io.bist.check);
|
||||||
|
|
|
@ -12,10 +12,11 @@ auto RSP::dmaTransferStep() -> void {
|
||||||
auto& region = !dma.current.pbusRegion ? dmem : imem;
|
auto& region = !dma.current.pbusRegion ? dmem : imem;
|
||||||
|
|
||||||
if(dma.busy.read) {
|
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) {
|
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);
|
u64 data = rdram.ram.read<Dual>(dma.current.dramAddress);
|
||||||
region.write<Dual>(dma.current.pbusAddress, data);
|
region.write<Dual>(dma.current.pbusAddress, data);
|
||||||
dma.current.dramAddress += 8;
|
dma.current.dramAddress += 8;
|
||||||
|
|
|
@ -36,7 +36,6 @@ auto RSP::r128::operator()(u32 index) const -> r128 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
static const __m128i shuffle[16] = {
|
static const __m128i shuffle[16] = {
|
||||||
//vector
|
//vector
|
||||||
_mm_set_epi8(15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), //01234567
|
_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
|
//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]))};
|
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 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);
|
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)));
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080);
|
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);
|
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);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vs0, slt;
|
r128 vs0, slt;
|
||||||
vs0 = _mm_cmpeq_epi16(vs, zero);
|
vs0 = _mm_cmpeq_epi16(vs, zero);
|
||||||
slt = _mm_srai_epi16(vs, 15);
|
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);
|
vd = _mm_xor_si128(vd, slt);
|
||||||
ACCL = _mm_sub_epi16(vd, slt);
|
ACCL = _mm_sub_epi16(vd, slt);
|
||||||
vd = _mm_subs_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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sum, min, max;
|
r128 vte = vt(e), sum, min, max;
|
||||||
sum = _mm_add_epi16(vs, vte);
|
sum = _mm_add_epi16(vs, vte);
|
||||||
ACCL = _mm_sub_epi16(sum, VCOL);
|
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);
|
vd = _mm_adds_epi16(min, max);
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +531,6 @@ auto RSP::VADDC(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sum;
|
r128 vte = vt(e), sum;
|
||||||
sum = _mm_adds_epu16(vs, vte);
|
sum = _mm_adds_epu16(vs, vte);
|
||||||
ACCL = _mm_add_epi16(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);
|
VCOL = _mm_cmpeq_epi16(VCOL, zero);
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,10 +552,8 @@ auto RSP::VAND(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_and_si128(vs, vt(e));
|
ACCL = _mm_and_si128(vs, vt(e));
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +584,6 @@ auto RSP::VCH(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), nvt, diff, diff0, vtn, dlez, dgez, mask;
|
r128 vte = vt(e), nvt, diff, diff0, vtn, dlez, dgez, mask;
|
||||||
VCOL = _mm_xor_si128(vs, vte);
|
VCOL = _mm_xor_si128(vs, vte);
|
||||||
VCOL = _mm_cmplt_epi16(VCOL, zero);
|
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);
|
mask = _mm_blendv_epi8(VCCH, VCCL, VCOL);
|
||||||
ACCL = _mm_blendv_epi8(vs, nvt, mask);
|
ACCL = _mm_blendv_epi8(vs, nvt, mask);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +639,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
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;
|
r128 vte = vt(e), nvt, diff, ncarry, nvce, diff0, lec1, lec2, leeq, geeq, le, ge, mask;
|
||||||
nvt = _mm_xor_si128(vte, VCOL);
|
nvt = _mm_xor_si128(vte, VCOL);
|
||||||
nvt = _mm_sub_epi16(nvt, VCOL);
|
nvt = _mm_sub_epi16(nvt, VCOL);
|
||||||
|
@ -683,7 +666,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
VCE = zero;
|
VCE = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,7 +689,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sign, dlez, dgez, nvt, mask;
|
r128 vte = vt(e), sign, dlez, dgez, nvt, mask;
|
||||||
sign = _mm_xor_si128(vs, vte);
|
sign = _mm_xor_si128(vs, vte);
|
||||||
sign = _mm_srai_epi16(sign, 15);
|
sign = _mm_srai_epi16(sign, 15);
|
||||||
|
@ -724,7 +705,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
VCE = zero;
|
VCE = zero;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +722,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), eq;
|
r128 vte = vt(e), eq;
|
||||||
eq = _mm_cmpeq_epi16(vs, vte);
|
eq = _mm_cmpeq_epi16(vs, vte);
|
||||||
VCCL = _mm_andnot_si128(VCOH, eq);
|
VCCL = _mm_andnot_si128(VCOH, eq);
|
||||||
|
@ -751,7 +730,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +747,6 @@ auto RSP::VGE(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), eq, gt, es;
|
r128 vte = vt(e), eq, gt, es;
|
||||||
eq = _mm_cmpeq_epi16(vs, vte);
|
eq = _mm_cmpeq_epi16(vs, vte);
|
||||||
gt = _mm_cmpgt_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;
|
VCOH = zero;
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,7 +775,6 @@ auto RSP::VLT(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), eq, lt;
|
r128 vte = vt(e), eq, lt;
|
||||||
eq = _mm_cmpeq_epi16(vs, vte);
|
eq = _mm_cmpeq_epi16(vs, vte);
|
||||||
lt = _mm_cmplt_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;
|
VCOH = zero;
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +805,6 @@ auto RSP::VMACF(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, md, hi, carry, omask;
|
r128 vte = vt(e), lo, md, hi, carry, omask;
|
||||||
lo = _mm_mullo_epi16(vs, vte);
|
lo = _mm_mullo_epi16(vs, vte);
|
||||||
hi = _mm_mulhi_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);
|
md = _mm_andnot_si128(hmask, md);
|
||||||
vd = _mm_or_si128(omask, 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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, hi, omask;
|
r128 vte = vt(e), lo, hi, omask;
|
||||||
lo = _mm_mullo_epi16(vs, vte);
|
lo = _mm_mullo_epi16(vs, vte);
|
||||||
hi = _mm_mulhi_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);
|
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||||
vd = _mm_packs_epi32(lo, hi);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), hi, omask, nhi, nmd, shi, smd, cmask, cval;
|
r128 vte = vt(e), hi, omask, nhi, nmd, shi, smd, cmask, cval;
|
||||||
hi = _mm_mulhi_epu16(vs, vte);
|
hi = _mm_mulhi_epu16(vs, vte);
|
||||||
omask = _mm_adds_epu16(ACCL, hi);
|
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);
|
cmask = _mm_and_si128(smd, shi);
|
||||||
cval = _mm_cmpeq_epi16(nhi, zero);
|
cval = _mm_cmpeq_epi16(nhi, zero);
|
||||||
vd = _mm_blendv_epi8(cval, ACCL, cmask);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, hi, sign, vta, omask;
|
r128 vte = vt(e), lo, hi, sign, vta, omask;
|
||||||
lo = _mm_mullo_epi16(vs, vte);
|
lo = _mm_mullo_epi16(vs, vte);
|
||||||
hi = _mm_mulhi_epu16(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);
|
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||||
vd = _mm_packs_epi32(lo, hi);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, hi, sign, vsa, omask, nhi, nmd, shi, smd, cmask, cval;
|
r128 vte = vt(e), lo, hi, sign, vsa, omask, nhi, nmd, shi, smd, cmask, cval;
|
||||||
lo = _mm_mullo_epi16(vs, vte);
|
lo = _mm_mullo_epi16(vs, vte);
|
||||||
hi = _mm_mulhi_epu16(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);
|
cmask = _mm_and_si128(smd, shi);
|
||||||
cval = _mm_cmpeq_epi16(nhi, zero);
|
cval = _mm_cmpeq_epi16(nhi, zero);
|
||||||
vd = _mm_blendv_epi8(cval, ACCL, cmask);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_blendv_epi8(vt(e), vs, VCCL);
|
ACCL = _mm_blendv_epi8(vt(e), vs, VCCL);
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,7 +1027,6 @@ auto RSP::VMUDH(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, hi;
|
r128 vte = vt(e), lo, hi;
|
||||||
ACCL = zero;
|
ACCL = zero;
|
||||||
ACCM = _mm_mullo_epi16(vs, vte);
|
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);
|
lo = _mm_unpacklo_epi16(ACCM, ACCH);
|
||||||
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
hi = _mm_unpackhi_epi16(ACCM, ACCH);
|
||||||
vd = _mm_packs_epi32(lo, hi);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_mulhi_epu16(vs, vt(e));
|
ACCL = _mm_mulhi_epu16(vs, vt(e));
|
||||||
ACCM = zero;
|
ACCM = zero;
|
||||||
ACCH = zero;
|
ACCH = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,7 +1066,6 @@ auto RSP::VMUDM(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sign, vta;
|
r128 vte = vt(e), sign, vta;
|
||||||
ACCL = _mm_mullo_epi16(vs, vte);
|
ACCL = _mm_mullo_epi16(vs, vte);
|
||||||
ACCM = _mm_mulhi_epu16(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);
|
ACCM = _mm_sub_epi16(ACCM, vta);
|
||||||
ACCH = _mm_srai_epi16(ACCM, 15);
|
ACCH = _mm_srai_epi16(ACCM, 15);
|
||||||
vd = ACCM;
|
vd = ACCM;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,7 +1088,6 @@ auto RSP::VMUDN(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sign, vsa;
|
r128 vte = vt(e), sign, vsa;
|
||||||
ACCL = _mm_mullo_epi16(vs, vte);
|
ACCL = _mm_mullo_epi16(vs, vte);
|
||||||
ACCM = _mm_mulhi_epu16(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);
|
ACCM = _mm_sub_epi16(ACCM, vsa);
|
||||||
ACCH = _mm_srai_epi16(ACCM, 15);
|
ACCH = _mm_srai_epi16(ACCM, 15);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1161,7 +1115,6 @@ auto RSP::VMULF(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), lo, hi, round, sign1, sign2, neq, eq, neg;
|
r128 vte = vt(e), lo, hi, round, sign1, sign2, neq, eq, neg;
|
||||||
lo = _mm_mullo_epi16(vs, vte);
|
lo = _mm_mullo_epi16(vs, vte);
|
||||||
round = _mm_cmpeq_epi16(zero, zero);
|
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);
|
hi = _mm_or_si128(ACCM, neg);
|
||||||
vd = _mm_andnot_si128(ACCH, hi);
|
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 constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_and_si128(vs, vt(e));
|
ACCL = _mm_and_si128(vs, vt(e));
|
||||||
ACCL = _mm_xor_si128(ACCL, invert);
|
ACCL = _mm_xor_si128(ACCL, invert);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,7 +1185,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), eq, ne;
|
r128 vte = vt(e), eq, ne;
|
||||||
eq = _mm_cmpeq_epi16(vs, vte);
|
eq = _mm_cmpeq_epi16(vs, vte);
|
||||||
ne = _mm_cmpeq_epi16(eq, zero);
|
ne = _mm_cmpeq_epi16(eq, zero);
|
||||||
|
@ -1246,7 +1195,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1264,11 +1212,9 @@ auto RSP::VNOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_or_si128(vs, vt(e));
|
ACCL = _mm_or_si128(vs, vt(e));
|
||||||
ACCL = _mm_xor_si128(ACCL, invert);
|
ACCL = _mm_xor_si128(ACCL, invert);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,11 +1229,9 @@ auto RSP::VNXOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_xor_si128(vs, vt(e));
|
ACCL = _mm_xor_si128(vs, vt(e));
|
||||||
ACCL = _mm_xor_si128(ACCL, invert);
|
ACCL = _mm_xor_si128(ACCL, invert);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1302,10 +1246,8 @@ auto RSP::VOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_or_si128(vs, vt(e));
|
ACCL = _mm_or_si128(vs, vt(e));
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,7 +1359,6 @@ auto RSP::VSUB(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), udiff, sdiff, ov;
|
r128 vte = vt(e), udiff, sdiff, ov;
|
||||||
udiff = _mm_sub_epi16(vte, VCOL);
|
udiff = _mm_sub_epi16(vte, VCOL);
|
||||||
sdiff = _mm_subs_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);
|
vd = _mm_adds_epi16(vd, ov);
|
||||||
VCOL = zero;
|
VCOL = zero;
|
||||||
VCOH = zero;
|
VCOH = zero;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1445,7 +1385,6 @@ auto RSP::VSUBC(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), equal, udiff, diff0;
|
r128 vte = vt(e), equal, udiff, diff0;
|
||||||
udiff = _mm_subs_epu16(vs, vte);
|
udiff = _mm_subs_epu16(vs, vte);
|
||||||
equal = _mm_cmpeq_epi16(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);
|
VCOL = _mm_andnot_si128(equal, diff0);
|
||||||
ACCL = _mm_sub_epi16(vs, vte);
|
ACCL = _mm_sub_epi16(vs, vte);
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1469,10 +1407,8 @@ auto RSP::VXOR(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
ACCL = _mm_xor_si128(vs, vt(e));
|
ACCL = _mm_xor_si128(vs, vt(e));
|
||||||
vd = ACCL;
|
vd = ACCL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1488,11 +1424,9 @@ auto RSP::VZERO(r128& vd, cr128& vs, cr128& vt) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr(Accuracy::RSP::SIMD) {
|
if constexpr(Accuracy::RSP::SIMD) {
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
|
||||||
r128 vte = vt(e), sum, min, max;
|
r128 vte = vt(e), sum, min, max;
|
||||||
ACCL = _mm_add_epi16(vs, vte);
|
ACCL = _mm_add_epi16(vs, vte);
|
||||||
vd = _mm_xor_si128(vd, vd);
|
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 {
|
auto RSP::writeWord(u32 address, u32 data) -> void {
|
||||||
if(address <= 0x0403'ffff) {
|
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);
|
else return dmem.write<Word>(address, data);
|
||||||
}
|
}
|
||||||
return ioWrite(address, data);
|
return ioWrite(address, data);
|
||||||
|
|
|
@ -1,35 +1,34 @@
|
||||||
auto RSP::Recompiler::pool() -> Pool* {
|
auto RSP::Recompiler::pool(u12 address) -> Pool* {
|
||||||
if(context) return context;
|
if(context[address >> 8]) return context[address >> 8];
|
||||||
|
|
||||||
nall::Hash::CRC32 hashcode;
|
auto hashcode = XXH3_64bits(self.imem.data + address, 256);
|
||||||
for(u32 offset : range(4096)) {
|
|
||||||
hashcode.input(self.imem.read<Byte>(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
PoolHashPair pair;
|
PoolHashPair pair;
|
||||||
pair.pool = (Pool*)allocator.acquire();
|
pair.pool = (Pool*)allocator.acquire();
|
||||||
pair.hashcode = hashcode.value();
|
pair.hashcode = hashcode;
|
||||||
if(auto result = pools.find(pair)) {
|
|
||||||
return context = result->pool;
|
auto result = pools[address >> 8].find(pair);
|
||||||
|
if(result) {
|
||||||
|
return context[address >> 8] = result->pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator.reserve(sizeof(Pool));
|
allocator.reserve(sizeof(Pool));
|
||||||
if(auto result = pools.insert(pair)) {
|
if(auto result = pools[address >> 8].insert(pair)) {
|
||||||
return context = result->pool;
|
return context[address >> 8] = result->pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw; //should never occur
|
throw; //should never occur
|
||||||
}
|
}
|
||||||
|
|
||||||
auto RSP::Recompiler::block(u32 address) -> Block* {
|
auto RSP::Recompiler::block(u12 address) -> Block* {
|
||||||
if(auto block = pool()->blocks[address >> 2 & 0x3ff]) return block;
|
if(auto block = pool(address)->blocks[address >> 2 & 0x3ff]) return block;
|
||||||
auto block = emit(address);
|
auto block = emit(address);
|
||||||
pool()->blocks[address >> 2 & 0x3ff] = block;
|
pool(address)->blocks[address >> 2 & 0x3ff] = block;
|
||||||
memory::jitprotect(true);
|
memory::jitprotect(true);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto RSP::Recompiler::emit(u32 address) -> Block* {
|
auto RSP::Recompiler::emit(u12 address) -> Block* {
|
||||||
if(unlikely(allocator.available() < 1_MiB)) {
|
if(unlikely(allocator.available() < 1_MiB)) {
|
||||||
print("RSP allocator flush\n");
|
print("RSP allocator flush\n");
|
||||||
memory::jitprotect(false);
|
memory::jitprotect(false);
|
||||||
|
|
|
@ -108,7 +108,7 @@ struct RSP : Thread, Memory::IO<RSP> {
|
||||||
};
|
};
|
||||||
|
|
||||||
r32 r[32];
|
r32 r[32];
|
||||||
u12 pc;
|
u16 pc; // previously u12; now u16 for performance.
|
||||||
} ipu;
|
} ipu;
|
||||||
|
|
||||||
struct Branch {
|
struct Branch {
|
||||||
|
@ -175,7 +175,7 @@ struct RSP : Thread, Memory::IO<RSP> {
|
||||||
//vpu.cpp: Vector Processing Unit
|
//vpu.cpp: Vector Processing Unit
|
||||||
union r128 {
|
union r128 {
|
||||||
struct { uint128_t u128; };
|
struct { uint128_t u128; };
|
||||||
#if defined(ARCHITECTURE_AMD64)
|
#if defined(ARCHITECTURE_AMD64) || defined(ARCHITECTURE_ARM64)
|
||||||
struct { __m128i v128; };
|
struct { __m128i v128; };
|
||||||
|
|
||||||
operator __m128i() const { return v128; }
|
operator __m128i() const { return v128; }
|
||||||
|
@ -350,18 +350,18 @@ struct RSP : Thread, Memory::IO<RSP> {
|
||||||
};
|
};
|
||||||
|
|
||||||
auto reset() -> void {
|
auto reset() -> void {
|
||||||
context = nullptr;
|
for(auto n : range(16)) context[n] = nullptr;
|
||||||
pools.reset();
|
for(auto n : range(16)) pools[n].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto invalidate() -> void {
|
auto invalidate(u32 address) -> void {
|
||||||
context = nullptr;
|
context[address >> 8] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pool() -> Pool*;
|
auto pool(u12 address) -> Pool*;
|
||||||
auto block(u32 address) -> Block*;
|
auto block(u12 address) -> Block*;
|
||||||
|
|
||||||
auto emit(u32 address) -> Block*;
|
auto emit(u12 address) -> Block*;
|
||||||
auto emitEXECUTE(u32 instruction) -> bool;
|
auto emitEXECUTE(u32 instruction) -> bool;
|
||||||
auto emitSPECIAL(u32 instruction) -> bool;
|
auto emitSPECIAL(u32 instruction) -> bool;
|
||||||
auto emitREGIMM(u32 instruction) -> bool;
|
auto emitREGIMM(u32 instruction) -> bool;
|
||||||
|
@ -371,9 +371,8 @@ struct RSP : Thread, Memory::IO<RSP> {
|
||||||
auto emitSWC2(u32 instruction) -> bool;
|
auto emitSWC2(u32 instruction) -> bool;
|
||||||
|
|
||||||
bump_allocator allocator;
|
bump_allocator allocator;
|
||||||
Pool* context = nullptr;
|
Pool* context[16];
|
||||||
set<PoolHashPair> pools;
|
set<PoolHashPair> pools[16];
|
||||||
//hashset<PoolHashPair> pools;
|
|
||||||
} recompiler{*this};
|
} recompiler{*this};
|
||||||
|
|
||||||
struct Disassembler {
|
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 {
|
struct Architecture {
|
||||||
static constexpr bool x86 = 0;
|
static constexpr bool x86 = 0;
|
||||||
static constexpr bool amd64 = 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 arm64 = 1;
|
||||||
static constexpr bool arm32 = 0;
|
static constexpr bool arm32 = 0;
|
||||||
static constexpr bool ppc64 = 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:
|
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
|
21.04.2022 - Non-backward compatible
|
||||||
Floating point comparison types are renamed.
|
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)/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)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \
|
||||||
$(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_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)/sljitNativeS390X.c \
|
||||||
$(SRCDIR)/sljitNativeX86_common.c $(SRCDIR)/sljitNativeX86_32.c $(SRCDIR)/sljitNativeX86_64.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_PPC_64 1 */
|
||||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||||
/* #define SLJIT_CONFIG_MIPS_64 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_S390X 1 */
|
||||||
|
|
||||||
/* #define SLJIT_CONFIG_AUTO 1 */
|
/* #define SLJIT_CONFIG_AUTO 1 */
|
||||||
|
@ -127,17 +128,6 @@ extern "C" {
|
||||||
|
|
||||||
#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
|
#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. */
|
/* Return with error when an invalid argument is passed. */
|
||||||
#ifndef SLJIT_ARGUMENT_CHECKS
|
#ifndef SLJIT_ARGUMENT_CHECKS
|
||||||
/* Disabled by default */
|
/* Disabled by default */
|
||||||
|
|
|
@ -59,7 +59,8 @@ extern "C" {
|
||||||
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
|
||||||
SLJIT_LITTLE_ENDIAN : little endian architecture
|
SLJIT_LITTLE_ENDIAN : little endian architecture
|
||||||
SLJIT_BIG_ENDIAN : big 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
|
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
|
||||||
|
|
||||||
Constants:
|
Constants:
|
||||||
|
@ -100,7 +101,6 @@ extern "C" {
|
||||||
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||||
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||||
+ (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
+ (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_S390X && SLJIT_CONFIG_S390X) \
|
||||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
+ (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_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||||
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
|
||||||
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
|
&& !(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_S390X && SLJIT_CONFIG_S390X) \
|
||||||
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
|
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
|
||||||
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
|
||||||
|
@ -164,8 +163,6 @@ extern "C" {
|
||||||
#define SLJIT_CONFIG_RISCV_32 1
|
#define SLJIT_CONFIG_RISCV_32 1
|
||||||
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
|
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
|
||||||
#define SLJIT_CONFIG_RISCV_64 1
|
#define SLJIT_CONFIG_RISCV_64 1
|
||||||
#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64)
|
|
||||||
#define SLJIT_CONFIG_SPARC_32 1
|
|
||||||
#elif defined(__s390x__)
|
#elif defined(__s390x__)
|
||||||
#define SLJIT_CONFIG_S390X 1
|
#define SLJIT_CONFIG_S390X 1
|
||||||
#else
|
#else
|
||||||
|
@ -215,8 +212,6 @@ extern "C" {
|
||||||
#define SLJIT_CONFIG_MIPS 1
|
#define SLJIT_CONFIG_MIPS 1
|
||||||
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
|
||||||
#define SLJIT_CONFIG_RISCV 1
|
#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
|
#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=91248
|
||||||
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
|
* 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) \
|
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||||
__builtin___clear_cache((char*)(from), (char*)(to))
|
__builtin___clear_cache((char*)(from), (char*)(to))
|
||||||
#endif
|
#endif
|
||||||
|
@ -389,13 +384,6 @@ extern "C" {
|
||||||
ppc_cache_flush((from), (to))
|
ppc_cache_flush((from), (to))
|
||||||
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
|
#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)
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
#define SLJIT_CACHE_FLUSH(from, to) \
|
#define SLJIT_CACHE_FLUSH(from, to) \
|
||||||
|
@ -512,8 +500,7 @@ typedef double sljit_f64;
|
||||||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||||
|
|
||||||
/* These macros are mostly useful for the applications. */
|
/* These macros are mostly useful for the applications. */
|
||||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
#define SLJIT_LITTLE_ENDIAN 1
|
#define SLJIT_LITTLE_ENDIAN 1
|
||||||
|
@ -521,8 +508,7 @@ typedef double sljit_f64;
|
||||||
#define SLJIT_BIG_ENDIAN 1
|
#define SLJIT_BIG_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
|
||||||
|
|
||||||
#ifdef __MIPSEL__
|
#ifdef __MIPSEL__
|
||||||
#define SLJIT_LITTLE_ENDIAN 1
|
#define SLJIT_LITTLE_ENDIAN 1
|
||||||
|
@ -549,8 +535,7 @@ typedef double sljit_f64;
|
||||||
|
|
||||||
#endif /* !SLJIT_MIPS_REV */
|
#endif /* !SLJIT_MIPS_REV */
|
||||||
|
|
||||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
|
||||||
|
|
||||||
#define SLJIT_BIG_ENDIAN 1
|
#define SLJIT_BIG_ENDIAN 1
|
||||||
|
|
||||||
|
@ -583,6 +568,18 @@ typedef double sljit_f64;
|
||||||
|
|
||||||
#endif /* !SLJIT_UNALIGNED */
|
#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)
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||||
/* Auto detect SSE2 support using CPUID.
|
/* Auto detect SSE2 support using CPUID.
|
||||||
On 64 bit x86 cpus, sse2 must be present. */
|
On 64 bit x86 cpus, sse2 must be present. */
|
||||||
|
@ -594,38 +591,7 @@ typedef double sljit_f64;
|
||||||
/*****************************************************************************************/
|
/*****************************************************************************************/
|
||||||
|
|
||||||
#ifndef SLJIT_FUNC
|
#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
|
#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 */
|
#endif /* !SLJIT_FUNC */
|
||||||
|
|
||||||
#ifndef SLJIT_INDIRECT_CALL
|
#ifndef SLJIT_INDIRECT_CALL
|
||||||
|
@ -640,11 +606,7 @@ typedef double sljit_f64;
|
||||||
/* The offset which needs to be substracted from the return address to
|
/* The offset which needs to be substracted from the return address to
|
||||||
determine the next executed instruction after return. */
|
determine the next executed instruction after return. */
|
||||||
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
|
#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
|
#define SLJIT_RETURN_ADDRESS_OFFSET 0
|
||||||
#endif
|
|
||||||
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
|
#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)
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||||
|
|
||||||
#define SLJIT_NUMBER_OF_REGISTERS 12
|
#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_FLOAT_REGISTERS 7
|
||||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
|
#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
|
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
|
||||||
|
|
||||||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
#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 */
|
#else /* _WIN64 */
|
||||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
|
||||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
|
#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 */
|
#endif /* !_WIN64 */
|
||||||
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
|
#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_FLOAT_REGISTERS 30
|
||||||
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
|
#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)
|
#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_PPC && SLJIT_CONFIG_PPC) \
|
||||||
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|
||||||
|| (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \
|
|
||||||
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||||
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
|
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -148,16 +148,16 @@
|
||||||
# define PATCH_MD 0x10
|
# define PATCH_MD 0x10
|
||||||
#endif
|
#endif
|
||||||
# define TYPE_SHIFT 13
|
# 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)
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||||
# define IS_BL 0x4
|
# define IS_BL 0x4
|
||||||
# define PATCH_B 0x8
|
# define PATCH_B 0x8
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||||
# define CPOOL_SIZE 512
|
# define CPOOL_SIZE 512
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_ARM_V5 */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||||
# define IS_COND 0x04
|
# define IS_COND 0x04
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
/* BL + imm24 */
|
/* BL + imm24 */
|
||||||
# define PATCH_BL 0x60
|
# define PATCH_BL 0x60
|
||||||
/* 0xf00 cc code for branches */
|
/* 0xf00 cc code for branches */
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_ARM_THUMB2 */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||||
# define IS_COND 0x004
|
# define IS_COND 0x004
|
||||||
|
@ -185,7 +185,7 @@
|
||||||
# define PATCH_COND 0x040
|
# define PATCH_COND 0x040
|
||||||
# define PATCH_ABS48 0x080
|
# define PATCH_ABS48 0x080
|
||||||
# define PATCH_ABS64 0x100
|
# define PATCH_ABS64 0x100
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_ARM_64 */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||||
# define IS_COND 0x004
|
# define IS_COND 0x004
|
||||||
|
@ -195,9 +195,9 @@
|
||||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||||
# define PATCH_ABS32 0x040
|
# define PATCH_ABS32 0x040
|
||||||
# define PATCH_ABS48 0x080
|
# define PATCH_ABS48 0x080
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_PPC_64 */
|
||||||
# define REMOVE_COND 0x100
|
# define REMOVE_COND 0x100
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_PPC */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||||
# define IS_MOVABLE 0x004
|
# define IS_MOVABLE 0x004
|
||||||
|
@ -215,7 +215,7 @@
|
||||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||||
# define PATCH_ABS32 0x400
|
# define PATCH_ABS32 0x400
|
||||||
# define PATCH_ABS48 0x800
|
# define PATCH_ABS48 0x800
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_MIPS_64 */
|
||||||
|
|
||||||
/* instruction types */
|
/* instruction types */
|
||||||
# define MOVABLE_INS 0
|
# define MOVABLE_INS 0
|
||||||
|
@ -224,7 +224,7 @@
|
||||||
# define UNMOVABLE_INS 32
|
# define UNMOVABLE_INS 32
|
||||||
/* FPU status register */
|
/* FPU status register */
|
||||||
# define FCSR_FCC 33
|
# define FCSR_FCC 33
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_MIPS */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||||
# define IS_COND 0x004
|
# define IS_COND 0x004
|
||||||
|
@ -241,28 +241,7 @@
|
||||||
#else /* !SLJIT_CONFIG_RISCV_64 */
|
#else /* !SLJIT_CONFIG_RISCV_64 */
|
||||||
# define PATCH_REL32 0x0
|
# define PATCH_REL32 0x0
|
||||||
#endif /* SLJIT_CONFIG_RISCV_64 */
|
#endif /* SLJIT_CONFIG_RISCV_64 */
|
||||||
#endif
|
#endif /* SLJIT_CONFIG_RISCV */
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
/* Stack management. */
|
/* Stack management. */
|
||||||
|
|
||||||
|
@ -457,10 +436,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
|
||||||
compiler->delay_slot = UNMOVABLE_INS;
|
compiler->delay_slot = UNMOVABLE_INS;
|
||||||
#endif
|
#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) \
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||||
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||||
compiler->last_flags = 0;
|
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))
|
if (!(p & SLJIT_MEM))
|
||||||
return 0;
|
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)))
|
if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -879,9 +857,6 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p
|
||||||
if (p == SLJIT_IMM)
|
if (p == SLJIT_IMM)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
|
||||||
return (i >= 0 && i < compiler->logical_local_size);
|
|
||||||
|
|
||||||
return function_check_src_mem(compiler, p, i);
|
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))
|
if (FUNCTION_CHECK_IS_REG(p))
|
||||||
return (i == 0);
|
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);
|
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))
|
if (FUNCTION_CHECK_IS_FREG(p))
|
||||||
return (i == 0);
|
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);
|
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_less", "ordered_greater_equal",
|
||||||
"unordered_or_greater", "ordered_less_equal",
|
"unordered_or_greater", "ordered_less_equal",
|
||||||
"jump", "fast_call",
|
"jump", "fast_call",
|
||||||
"call", "call.cdecl"
|
"call", "call_reg_arg"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* call_arg_names[] = {
|
static const char* call_arg_names[] = {
|
||||||
|
@ -1079,6 +1048,8 @@ static const char* call_arg_names[] = {
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
||||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
|| (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)
|
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)
|
||||||
{
|
{
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#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);
|
SLJIT_UNUSED_ARG(compiler);
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
|
if (options & SLJIT_ENTER_REG_ARG) {
|
||||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
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(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
||||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_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(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
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((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;
|
compiler->last_flags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1138,10 +1113,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
|
||||||
|
|
||||||
fprintf(compiler->verbose, "],");
|
fprintf(compiler->verbose, "],");
|
||||||
|
|
||||||
if (options & SLJIT_ENTER_CDECL)
|
if (options & SLJIT_ENTER_REG_ARG) {
|
||||||
fprintf(compiler->verbose, " enter:cdecl,");
|
fprintf(compiler->verbose, " enter:reg_arg,");
|
||||||
|
|
||||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
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",
|
fprintf(compiler->verbose, "scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
|
||||||
scratches, saveds, fscratches, fsaveds, local_size);
|
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);
|
SLJIT_UNUSED_ARG(compiler);
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
|
if (options & SLJIT_ENTER_REG_ARG) {
|
||||||
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
|
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(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
|
||||||
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
|
||||||
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_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(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
|
||||||
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
|
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((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;
|
compiler->last_flags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1189,10 +1170,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
|
||||||
|
|
||||||
fprintf(compiler->verbose, "],");
|
fprintf(compiler->verbose, "],");
|
||||||
|
|
||||||
if (options & SLJIT_ENTER_CDECL)
|
if (options & SLJIT_ENTER_REG_ARG) {
|
||||||
fprintf(compiler->verbose, " enter:cdecl,");
|
fprintf(compiler->verbose, " enter:reg_arg,");
|
||||||
|
|
||||||
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
|
||||||
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
|
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",
|
fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
|
||||||
scratches, saveds, fscratches, fsaveds, local_size);
|
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)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
|
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));
|
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_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
|
#endif
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
#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)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
|
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));
|
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
|
||||||
FUNCTION_CHECK_SRC(src, srcw);
|
FUNCTION_CHECK_SRC(src, srcw);
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_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
|
#endif
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
#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)
|
sljit_s32 mem, sljit_sw memw)
|
||||||
{
|
{
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#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 & 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_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) || (type & SLJIT_MEM_POST));
|
||||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | 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 & ~(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);
|
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
|
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
|
||||||
|
|
||||||
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
|
|
||||||
#endif
|
#endif
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||||
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
|
||||||
fprintf(compiler->verbose, " //");
|
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 ",
|
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_32) ? "" : "32",
|
||||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||||
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
|
op1_names[(type & 0xff) - SLJIT_OP1_BASE]);
|
||||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
|
||||||
|
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);
|
sljit_verbose_reg(compiler, reg);
|
||||||
fprintf(compiler->verbose, ", ");
|
fprintf(compiler->verbose, ", ");
|
||||||
sljit_verbose_param(compiler, mem, memw);
|
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)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
|
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
|
||||||
|
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) || (type & SLJIT_MEM_POST));
|
||||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | 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 & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
|
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
|
||||||
#endif
|
#endif
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||||
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
|
||||||
fprintf(compiler->verbose, " //");
|
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_MEM_STORE) ? "st" : "ld",
|
||||||
!(type & SLJIT_32) ? ".f64" : ".f32",
|
!(type & SLJIT_32) ? ".f64" : ".f32");
|
||||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
|
||||||
|
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);
|
sljit_verbose_freg(compiler, freg);
|
||||||
fprintf(compiler->verbose, ", ");
|
fprintf(compiler->verbose, ", ");
|
||||||
sljit_verbose_param(compiler, mem, memw);
|
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;
|
CHECK_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */
|
||||||
|
|
||||||
|
#define SLJIT_SKIP_CHECKS(compiler)
|
||||||
|
|
||||||
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
|
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
|
||||||
|
|
||||||
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
|
#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;
|
return SLJIT_SUCCESS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
|
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)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
|
||||||
{
|
{
|
||||||
CHECK_ERROR();
|
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));
|
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_return_void(compiler);
|
return sljit_emit_return_void(compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||||
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
|| (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_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \
|
||||||
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
|| (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;
|
struct sljit_jump *jump;
|
||||||
sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV;
|
sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV;
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
jump = sljit_emit_jump(compiler, type ^ 0x1);
|
jump = sljit_emit_jump(compiler, type ^ 0x1);
|
||||||
FAIL_IF(!jump);
|
FAIL_IF(!jump);
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw));
|
FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
label = sljit_emit_label(compiler);
|
label = sljit_emit_label(compiler);
|
||||||
FAIL_IF(!label);
|
FAIL_IF(!label);
|
||||||
|
|
||||||
sljit_set_label(jump, label);
|
sljit_set_label(jump, label);
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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 */
|
/* CPU description section */
|
||||||
|
|
||||||
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
|
#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"
|
# include "sljitNativeMIPS_common.c"
|
||||||
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
|
||||||
# include "sljitNativeRISCV_common.c"
|
# include "sljitNativeRISCV_common.c"
|
||||||
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
|
|
||||||
# include "sljitNativeSPARC_common.c"
|
|
||||||
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||||
# include "sljitNativeS390X.c"
|
# include "sljitNativeS390X.c"
|
||||||
#endif
|
#endif
|
||||||
|
@ -2286,16 +2347,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
||||||
else
|
else
|
||||||
flags = condition << VARIABLE_FLAG_SHIFT;
|
flags = condition << VARIABLE_FLAG_SHIFT;
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
PTR_FAIL_IF(sljit_emit_op2u(compiler,
|
PTR_FAIL_IF(sljit_emit_op2u(compiler,
|
||||||
SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
|
SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));
|
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_ERROR_PTR();
|
||||||
CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
|
CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);
|
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) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_jump(compiler, type);
|
return sljit_emit_jump(compiler, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|
||||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|
||||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
sljit_s32 reg,
|
sljit_s32 reg,
|
||||||
sljit_s32 mem, sljit_sw memw)
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||||
|
|
||||||
|
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
|
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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)
|
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
sljit_s32 freg,
|
sljit_s32 freg,
|
||||||
sljit_s32 mem, sljit_sw memw)
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||||
|
|
||||||
|
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
|
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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));
|
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
|
||||||
|
|
||||||
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
|
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
|
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);
|
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)
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||||
sljit_s32 args_size;
|
sljit_s32 args_size;
|
||||||
sljit_s32 locals_offset;
|
|
||||||
sljit_s32 scratches_offset;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||||
|
@ -493,12 +491,6 @@ struct sljit_compiler {
|
||||||
sljit_sw cache_argw;
|
sljit_sw cache_argw;
|
||||||
#endif
|
#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)
|
#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
|
||||||
/* Need to allocate register save area to make calls. */
|
/* Need to allocate register save area to make calls. */
|
||||||
sljit_s32 mode;
|
sljit_s32 mode;
|
||||||
|
@ -702,17 +694,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type);
|
||||||
overwrites the previous context.
|
overwrites the previous context.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The SLJIT_S0/SLJIT_S1 registers are not saved / restored on function
|
/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive)
|
||||||
enter / return. Instead, these registers can be used to pass / return
|
are not saved / restored on function enter / return. Instead,
|
||||||
data (such as global / local context pointers) across function calls.
|
these registers can be used to pass / return data (such as
|
||||||
This is an sljit specific (non ABI compatible) function call extension
|
global / local context pointers) across function calls. The
|
||||||
so both the caller and called function must be compiled by sljit. */
|
value of n must be between 1 and 3. Furthermore, this option
|
||||||
#define SLJIT_ENTER_KEEP_S0 0x00000001
|
is only supported by register argument calling convention, so
|
||||||
#define SLJIT_ENTER_KEEP_S0_S1 0x00000002
|
SLJIT_ENTER_REG_ARG (see below) must be specified as well. */
|
||||||
|
#define SLJIT_ENTER_KEEP(n) (n)
|
||||||
|
|
||||||
/* The compiled function uses cdecl calling
|
/* The compiled function uses an sljit specific register argument
|
||||||
* convention instead of SLJIT_FUNC. */
|
* calling convention. This is a lightweight function call type where
|
||||||
#define SLJIT_ENTER_CDECL 0x00000004
|
* 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. */
|
/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
|
||||||
#define SLJIT_MAX_LOCAL_SIZE 65536
|
#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
|
Write-back is supported except for one instruction: 32 bit signed
|
||||||
load with [reg+imm] addressing mode on 64 bit.
|
load with [reg+imm] addressing mode on 64 bit.
|
||||||
mips: [reg+imm], -65536 <= imm <= 65535
|
mips: [reg+imm], -65536 <= imm <= 65535
|
||||||
sparc: [reg+imm], -4096 <= imm <= 4095
|
Write-back is not supported
|
||||||
[reg+reg] is supported
|
riscv: [reg+imm], -2048 <= imm <= 2047
|
||||||
|
Write-back is not supported
|
||||||
s390x: [reg+imm], -2^19 <= imm < 2^19
|
s390x: [reg+imm], -2^19 <= imm < 2^19
|
||||||
[reg+reg] is supported
|
[reg+reg] is supported
|
||||||
Write-back is not 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
|
#define SLJIT_JUMP 34
|
||||||
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
|
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
|
||||||
#define SLJIT_FAST_CALL 35
|
#define SLJIT_FAST_CALL 35
|
||||||
/* Called function must be declared with the SLJIT_FUNC attribute. */
|
/* Default C calling convention. */
|
||||||
#define SLJIT_CALL 36
|
#define SLJIT_CALL 36
|
||||||
/* Called function must be declared with cdecl attribute.
|
/* Called function must be an sljit compiled function.
|
||||||
This is the default attribute for C functions. */
|
See SLJIT_ENTER_REG_ARG option. */
|
||||||
#define SLJIT_CALL_CDECL 37
|
#define SLJIT_CALL_REG_ARG 37
|
||||||
|
|
||||||
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
|
||||||
#define SLJIT_REWRITABLE_JUMP 0x1000
|
#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
|
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
|
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
|
to zero. In the latter case the compiler needs to allocate space for some
|
||||||
arguments and the return register must be kept as well.
|
arguments and the return address must be stored on the stack as well. */
|
||||||
|
|
||||||
This feature is highly experimental and not supported on SPARC platform
|
|
||||||
at the moment. */
|
|
||||||
#define SLJIT_CALL_RETURN 0x2000
|
#define SLJIT_CALL_RETURN 0x2000
|
||||||
|
|
||||||
/* Emit a jump instruction. The destination is not set, only the type of the jump.
|
/* 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(). */
|
/* 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.
|
/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
|
||||||
Instead the function returns with SLJIT_SUCCESS if the instruction
|
Instead the function returns with SLJIT_SUCCESS if the instruction
|
||||||
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
|
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
|
||||||
allows runtime checking of available instruction forms. */
|
allows runtime checking of available instruction forms. */
|
||||||
#define SLJIT_MEM_SUPP 0x0200
|
#define SLJIT_MEM_SUPP 0x010000
|
||||||
/* 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
|
|
||||||
|
|
||||||
/* Emit a single memory load or store with update instruction. When the
|
/* The sljit_emit_mem emits instructions for various memory operations:
|
||||||
requested instruction form is not supported by the CPU, it returns
|
|
||||||
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
|
When SLJIT_MEM_UNALIGNED is set in type argument:
|
||||||
allows specializing tight loops based on the supported instruction
|
Emit instructions for unaligned memory loads or stores. When
|
||||||
forms (see SLJIT_MEM_SUPP flag).
|
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
|
type must be between SLJIT_MOV and SLJIT_MOV_P and can be
|
||||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
combined with SLJIT_MEM_* flags.
|
||||||
or SLJIT_MEM_POST must be specified.
|
|
||||||
reg is the source or destination register, and must be
|
reg is the source or destination register, and must be
|
||||||
different from the base register of the mem operand
|
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) */
|
Flags: - (does not modify flags) */
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
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:
|
/* Same as sljit_emit_mem except the followings:
|
||||||
|
|
||||||
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
|
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
|
||||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
combined with SLJIT_MEM_* flags.
|
||||||
or SLJIT_MEM_POST must be specified.
|
freg is the source or destination floating point register
|
||||||
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_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
sljit_s32 freg,
|
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.
|
/* 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.
|
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);
|
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 CMP 0xe1400000
|
||||||
#define BKPT 0xe1200070
|
#define BKPT 0xe1200070
|
||||||
#define EOR 0xe0200000
|
#define EOR 0xe0200000
|
||||||
|
#define LDR 0xe5100000
|
||||||
#define MOV 0xe1a00000
|
#define MOV 0xe1a00000
|
||||||
#define MUL 0xe0000090
|
#define MUL 0xe0000090
|
||||||
#define MVN 0xe1e00000
|
#define MVN 0xe1e00000
|
||||||
|
@ -111,6 +112,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
|
||||||
#define RSC 0xe0e00000
|
#define RSC 0xe0e00000
|
||||||
#define SBC 0xe0c00000
|
#define SBC 0xe0c00000
|
||||||
#define SMULL 0xe0c00090
|
#define SMULL 0xe0c00090
|
||||||
|
#define STR 0xe5000000
|
||||||
#define SUB 0xe0400000
|
#define SUB 0xe0400000
|
||||||
#define TST 0xe1000000
|
#define TST 0xe1000000
|
||||||
#define UMULL 0xe0800090
|
#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;
|
local_size = ((size + local_size + 0x7) & ~0x7) - size;
|
||||||
compiler->local_size = local_size;
|
compiler->local_size = local_size;
|
||||||
|
|
||||||
|
if (options & SLJIT_ENTER_REG_ARG)
|
||||||
|
arg_types = 0;
|
||||||
|
|
||||||
arg_types >>= SLJIT_ARG_SHIFT;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
word_arg_count = 0;
|
word_arg_count = 0;
|
||||||
|
saved_arg_count = 0;
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
|
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))
|
if (offset < 4 * sizeof(sljit_sw))
|
||||||
FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
|
FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
|
||||||
else
|
else
|
||||||
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
|
FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
|
||||||
| RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,8 +1315,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
|
||||||
lr_dst = SLJIT_FIRST_SAVED_REG;
|
lr_dst = SLJIT_FIRST_SAVED_REG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
|
return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
|
||||||
| RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_size > 0)
|
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_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
||||||
{
|
{
|
||||||
sljit_uw imm, offset_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 & 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 (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||||
if (is_type1_transfer) {
|
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)(argw & ~mask)));
|
||||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));
|
argw &= mask;
|
||||||
argw &= 0xfff;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));
|
|
||||||
argw &= 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,
|
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) {
|
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;
|
arg &= REG_MASK;
|
||||||
argw &= 0x3;
|
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)));
|
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)));
|
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bit 25: RM is offset. */
|
/* Bit 25: RM is offset. */
|
||||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
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;
|
arg &= REG_MASK;
|
||||||
|
|
||||||
if (is_type1_transfer) {
|
if (argw > mask) {
|
||||||
if (argw > 0xfff) {
|
imm = get_imm((sljit_uw)(argw & ~mask));
|
||||||
imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
|
||||||
if (imm) {
|
if (imm) {
|
||||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||||
argw = argw & 0xfff;
|
argw = argw & mask;
|
||||||
arg = tmp_reg;
|
arg = tmp_reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (argw < -0xfff) {
|
else if (argw < -mask) {
|
||||||
imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);
|
imm = get_imm((sljit_uw)(-argw & ~mask));
|
||||||
if (imm) {
|
if (imm) {
|
||||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||||
argw = -(-argw & 0xfff);
|
argw = -(-argw & mask);
|
||||||
arg = tmp_reg;
|
arg = tmp_reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argw >= 0 && argw <= 0xfff)
|
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));
|
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 < -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 >= 0 && argw <= 0xff)
|
|
||||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
|
||||||
|
|
||||||
if (argw < 0 && argw >= -0xff) {
|
|
||||||
argw = -argw;
|
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));
|
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
|
||||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
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,
|
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;
|
saved_reg_list[saved_reg_count++] = 1;
|
||||||
|
|
||||||
if (saved_reg_count > 0) {
|
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]! */));
|
| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
|
||||||
if (saved_reg_count >= 2) {
|
if (saved_reg_count >= 2) {
|
||||||
SLJIT_ASSERT(saved_reg_list[1] < 8);
|
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) {
|
if (saved_reg_count >= 3) {
|
||||||
SLJIT_ASSERT(saved_reg_list[2] < 8);
|
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 > 0) {
|
||||||
if (saved_reg_count >= 3) {
|
if (saved_reg_count >= 3) {
|
||||||
SLJIT_ASSERT(saved_reg_list[2] < 8);
|
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) {
|
if (saved_reg_count >= 2) {
|
||||||
SLJIT_ASSERT(saved_reg_list[1] < 8);
|
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 */);
|
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
|
||||||
}
|
}
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
|
@ -2095,10 +2074,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
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;
|
return SLJIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FPU_LOAD
|
|
||||||
#undef EMIT_FPU_DATA_TRANSFER
|
#undef EMIT_FPU_DATA_TRANSFER
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -2482,7 +2457,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
|
||||||
return 0x50000000;
|
return 0x50000000;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
|
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
|
||||||
return 0xe0000000;
|
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)));
|
FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
|
||||||
} else
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2738,17 +2713,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||||
|
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||||
|
|
||||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
jump = sljit_emit_jump(compiler, type);
|
jump = sljit_emit_jump(compiler, type);
|
||||||
PTR_FAIL_IF(jump == NULL);
|
PTR_FAIL_IF(jump == NULL);
|
||||||
|
|
||||||
|
@ -2768,21 +2740,21 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||||
return jump;
|
return jump;
|
||||||
#else /* !__SOFTFP__ */
|
}
|
||||||
|
#endif /* __SOFTFP__ */
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||||
|
#endif /* !__SOFTFP__ */
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||||
|
@ -2848,17 +2820,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||||
|
|
||||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||||
type = SLJIT_JUMP;
|
type = SLJIT_JUMP;
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||||
|
|
||||||
if (extra_space > 0) {
|
if (extra_space > 0) {
|
||||||
|
@ -2874,21 +2843,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
||||||
|
|
||||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||||
return softfloat_post_call_with_args(compiler, arg_types);
|
return softfloat_post_call_with_args(compiler, arg_types);
|
||||||
#else /* !__SOFTFP__ */
|
}
|
||||||
|
#endif /* __SOFTFP__ */
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||||
type = SLJIT_JUMP;
|
type = SLJIT_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||||
|
#endif /* !__SOFTFP__ */
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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,
|
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);
|
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_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
sljit_s32 reg,
|
sljit_s32 reg,
|
||||||
sljit_s32 mem, sljit_sw memw)
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
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;
|
is_type1_transfer = 1;
|
||||||
|
|
||||||
switch (type & 0xff) {
|
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));
|
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)
|
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_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -1001,15 +1001,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||||
if (prev != -1)
|
if (prev != -1)
|
||||||
FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
|
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
|
#ifdef _WIN32
|
||||||
if (local_size > 4096)
|
if (local_size > 4096)
|
||||||
FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
|
FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||||
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
|
saved_arg_count = 0;
|
||||||
tmp = SLJIT_R0;
|
tmp = SLJIT_R0;
|
||||||
while (arg_types > 0) {
|
|
||||||
|
while (arg_types) {
|
||||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
||||||
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
|
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)));
|
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp)));
|
||||||
|
@ -1019,6 +1022,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||||
}
|
}
|
||||||
arg_types >>= SLJIT_ARG_SHIFT;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (local_size > 4096) {
|
if (local_size > 4096) {
|
||||||
|
@ -1390,10 +1394,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
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);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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;
|
type = SLJIT_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
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))
|
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -2070,6 +2066,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
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))
|
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
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 HALF_SIZE 0x08
|
||||||
#define PRELOAD 0x0c
|
#define PRELOAD 0x0c
|
||||||
|
|
||||||
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
|
#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))
|
||||||
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
|
#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1st letter:
|
1st letter:
|
||||||
|
@ -993,8 +993,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
||||||
sljit_uw tmp;
|
sljit_uw tmp;
|
||||||
|
|
||||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
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 >= -0xff && argw <= 0xfff));
|
||||||
arg &= ~SLJIT_MEM;
|
|
||||||
|
|
||||||
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||||
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
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)) {
|
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||||
argw &= 0x3;
|
argw &= 0x3;
|
||||||
other_r = OFFS_REG(arg);
|
other_r = OFFS_REG(arg);
|
||||||
arg &= 0xf;
|
arg &= REG_MASK;
|
||||||
|
|
||||||
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
|
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_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));
|
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg &= REG_MASK;
|
||||||
|
|
||||||
if (argw > 0xfff) {
|
if (argw > 0xfff) {
|
||||||
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
|
tmp = get_imm((sljit_uw)(argw & ~0xfff));
|
||||||
if (tmp != INVALID_IMM) {
|
if (tmp != INVALID_IMM) {
|
||||||
push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
||||||
arg = tmp_reg;
|
arg = tmp_reg;
|
||||||
|
@ -1028,7 +1029,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (argw < -0xff) {
|
else if (argw < -0xff) {
|
||||||
tmp = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
|
tmp = get_imm((sljit_uw)(-argw & ~0xff));
|
||||||
if (tmp != INVALID_IMM) {
|
if (tmp != INVALID_IMM) {
|
||||||
push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
|
||||||
arg = tmp_reg;
|
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]) {
|
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
|
||||||
tmp = 3;
|
tmp = 3;
|
||||||
if (IS_WORD_SIZE(flags)) {
|
if (IS_WORD_SIZE(flags)) {
|
||||||
if (OFFSET_CHECK(0x1f, 2))
|
if (ALIGN_CHECK(argw, 0x1f, 2))
|
||||||
tmp = 2;
|
tmp = 2;
|
||||||
}
|
}
|
||||||
else if (flags & BYTE_SIZE)
|
else if (flags & BYTE_SIZE)
|
||||||
{
|
{
|
||||||
if (OFFSET_CHECK(0x1f, 0))
|
if (ALIGN_CHECK(argw, 0x1f, 0))
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SLJIT_ASSERT(flags & HALF_SIZE);
|
SLJIT_ASSERT(flags & HALF_SIZE);
|
||||||
if (OFFSET_CHECK(0x1f, 1))
|
if (ALIGN_CHECK(argw, 0x1f, 1))
|
||||||
tmp = 1;
|
tmp = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp < 3)
|
if (tmp < 3)
|
||||||
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));
|
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. */
|
/* SP based immediate. */
|
||||||
return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));
|
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));
|
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef ALIGN_CHECK
|
||||||
|
#undef IS_WORD_SIZE
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Entry, exit */
|
/* 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;
|
local_size = ((size + local_size + 0x7) & ~0x7) - size;
|
||||||
compiler->local_size = local_size;
|
compiler->local_size = local_size;
|
||||||
|
|
||||||
|
if (options & SLJIT_ENTER_REG_ARG)
|
||||||
|
arg_types = 0;
|
||||||
|
|
||||||
arg_types >>= SLJIT_ARG_SHIFT;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
word_arg_count = 0;
|
word_arg_count = 0;
|
||||||
|
saved_arg_count = 0;
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
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);
|
return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FPU_LOAD
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Other instructions */
|
/* Other instructions */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -2310,17 +2314,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||||
|
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||||
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
|
||||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||||
|
|
||||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
jump = sljit_emit_jump(compiler, type);
|
jump = sljit_emit_jump(compiler, type);
|
||||||
PTR_FAIL_IF(jump == NULL);
|
PTR_FAIL_IF(jump == NULL);
|
||||||
|
|
||||||
|
@ -2340,22 +2341,22 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||||
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
|
||||||
return jump;
|
return jump;
|
||||||
#else
|
}
|
||||||
|
#endif /* __SOFTFP__ */
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
/* ldmia sp!, {..., lr} */
|
/* ldmia sp!, {..., lr} */
|
||||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||||
|
#endif /* !__SOFTFP__ */
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
|
||||||
|
@ -2412,17 +2413,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __SOFTFP__
|
#ifdef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||||
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
|
||||||
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
SLJIT_ASSERT((extra_space & 0x7) == 0);
|
||||||
|
|
||||||
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
|
||||||
type = SLJIT_JUMP;
|
type = SLJIT_JUMP;
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
|
||||||
|
|
||||||
if (extra_space > 0) {
|
if (extra_space > 0) {
|
||||||
|
@ -2438,22 +2436,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
||||||
|
|
||||||
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
|
||||||
return softfloat_post_call_with_args(compiler, arg_types);
|
return softfloat_post_call_with_args(compiler, arg_types);
|
||||||
#else /* !__SOFTFP__ */
|
}
|
||||||
|
#endif /* __SOFTFP__ */
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
/* ldmia sp!, {..., lr} */
|
/* ldmia sp!, {..., lr} */
|
||||||
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
FAIL_IF(emit_stack_frame_release(compiler, -1));
|
||||||
type = SLJIT_JUMP;
|
type = SLJIT_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __SOFTFP__
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
|
||||||
|
#endif /* !__SOFTFP__ */
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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,
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
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))
|
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
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);
|
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)
|
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_;
|
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)
|
sljit_s32 arg_types)
|
||||||
{
|
{
|
||||||
struct sljit_jump *jump;
|
struct sljit_jump *jump;
|
||||||
sljit_u32 extra_space = (sljit_u32)type;
|
sljit_u32 extra_space = 0;
|
||||||
sljit_ins ins;
|
sljit_ins ins = NOP;
|
||||||
|
|
||||||
CHECK_ERROR_PTR();
|
CHECK_ERROR_PTR();
|
||||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
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);
|
PTR_FAIL_IF(!jump);
|
||||||
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
|
||||||
|
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
|
||||||
|
extra_space = (sljit_u32)type;
|
||||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
|
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);
|
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) {
|
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));
|
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||||
} else
|
} else
|
||||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
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);
|
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||||
|
|
||||||
if (src & SLJIT_IMM)
|
if (src & SLJIT_IMM)
|
||||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
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)));
|
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));
|
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)
|
if (type & SLJIT_CALL_RETURN)
|
||||||
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
||||||
|
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
|
||||||
|
|
||||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
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)) {
|
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));
|
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||||
} else
|
} else
|
||||||
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
|
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);
|
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||||
|
|
||||||
if (src & SLJIT_IMM)
|
if (src & SLJIT_IMM)
|
||||||
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
|
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)));
|
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)
|
if (type & SLJIT_CALL_RETURN)
|
||||||
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
|
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))
|
#define JR (HI(0) | LO(8))
|
||||||
#endif /* SLJIT_MIPS_REV >= 6 */
|
#endif /* SLJIT_MIPS_REV >= 6 */
|
||||||
#define LD (HI(55))
|
#define LD (HI(55))
|
||||||
|
#define LDL (HI(26))
|
||||||
|
#define LDR (HI(27))
|
||||||
#define LDC1 (HI(53))
|
#define LDC1 (HI(53))
|
||||||
#define LUI (HI(15))
|
#define LUI (HI(15))
|
||||||
#define LW (HI(35))
|
#define LW (HI(35))
|
||||||
|
#define LWL (HI(34))
|
||||||
|
#define LWR (HI(38))
|
||||||
#define LWC1 (HI(49))
|
#define LWC1 (HI(49))
|
||||||
#define MFC1 (HI(17))
|
#define MFC1 (HI(17))
|
||||||
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
|
#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 OR (HI(0) | LO(37))
|
||||||
#define ORI (HI(13))
|
#define ORI (HI(13))
|
||||||
#define SD (HI(63))
|
#define SD (HI(63))
|
||||||
|
#define SDL (HI(44))
|
||||||
|
#define SDR (HI(45))
|
||||||
#define SDC1 (HI(61))
|
#define SDC1 (HI(61))
|
||||||
#define SLT (HI(0) | LO(42))
|
#define SLT (HI(0) | LO(42))
|
||||||
#define SLTI (HI(10))
|
#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 SUB_S (HI(17) | FMT_S | LO(1))
|
||||||
#define SUBU (HI(0) | LO(35))
|
#define SUBU (HI(0) | LO(35))
|
||||||
#define SW (HI(43))
|
#define SW (HI(43))
|
||||||
|
#define SWL (HI(42))
|
||||||
|
#define SWR (HI(46))
|
||||||
#define SWC1 (HI(57))
|
#define SWC1 (HI(57))
|
||||||
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
|
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
|
||||||
#define XOR (HI(0) | LO(38))
|
#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 ADDU_W ADDU
|
||||||
#define ADDIU_W ADDIU
|
#define ADDIU_W ADDIU
|
||||||
#define SLL_W SLL
|
#define SLL_W SLL
|
||||||
|
#define SRA_W SRA
|
||||||
#define SUBU_W SUBU
|
#define SUBU_W SUBU
|
||||||
#else
|
#else
|
||||||
#define ADDU_W DADDU
|
#define ADDU_W DADDU
|
||||||
#define ADDIU_W DADDIU
|
#define ADDIU_W DADDIU
|
||||||
#define SLL_W DSLL
|
#define SLL_W DSLL
|
||||||
|
#define SRA_W DSRA
|
||||||
#define SUBU_W DSUBU
|
#define SUBU_W DSUBU
|
||||||
#endif
|
#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);
|
jump->addr -= 2 * sizeof(sljit_ins);
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
|
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
|
||||||
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
|
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
|
||||||
jump->flags |= PATCH_B;
|
jump->flags |= PATCH_B;
|
||||||
|
|
||||||
if (!(jump->flags & IS_COND)) {
|
if (!(jump->flags & IS_COND)) {
|
||||||
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
|
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
|
||||||
inst[1] = NOP;
|
/* Keep inst[1] */
|
||||||
return inst + 1;
|
return inst + 1;
|
||||||
}
|
}
|
||||||
inst[0] ^= invert_branch(jump->flags);
|
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)) {
|
if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
|
||||||
jump->flags |= PATCH_J;
|
jump->flags |= PATCH_J;
|
||||||
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
|
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
|
||||||
inst[1] = NOP;
|
/* Keep inst[1] */
|
||||||
return inst + 1;
|
return inst + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -802,10 +811,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||||
#endif
|
#endif
|
||||||
compiler->local_size = local_size;
|
compiler->local_size = local_size;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||||
|
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||||
tmp = arg_types >> SLJIT_ARG_SHIFT;
|
tmp = arg_types >> SLJIT_ARG_SHIFT;
|
||||||
arg_count = 0;
|
arg_count = 0;
|
||||||
offset = 0;
|
|
||||||
|
|
||||||
while (tmp) {
|
while (tmp) {
|
||||||
offset = arg_count;
|
offset = arg_count;
|
||||||
|
@ -821,8 +831,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
|
||||||
|
|
||||||
compiler->args_size = (sljit_uw)arg_count << 2;
|
compiler->args_size = (sljit_uw)arg_count << 2;
|
||||||
offset = (offset >= 4) ? (offset << 2) : 0;
|
offset = (offset >= 4) ? (offset << 2) : 0;
|
||||||
#else /* !SLJIT_CONFIG_MIPS_32 */
|
}
|
||||||
offset = 0;
|
|
||||||
#endif /* SLJIT_CONFIG_MIPS_32 */
|
#endif /* SLJIT_CONFIG_MIPS_32 */
|
||||||
|
|
||||||
if (local_size + offset <= -SIMM_MIN) {
|
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);
|
base = S(SLJIT_SP);
|
||||||
offset = local_size - SSIZE_OF(sw);
|
offset = local_size - SSIZE_OF(sw);
|
||||||
} else {
|
} 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, 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);
|
base = S(TMP_REG2);
|
||||||
offset = -SSIZE_OF(sw);
|
offset = -SSIZE_OF(sw);
|
||||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
#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));
|
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_types >>= SLJIT_ARG_SHIFT;
|
||||||
arg_count = 0;
|
arg_count = 0;
|
||||||
word_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);
|
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)
|
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))
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
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));
|
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
|
||||||
|
|
||||||
if (FAST_IS_REG(dst))
|
if (FAST_IS_REG(dst)) {
|
||||||
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
|
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. */
|
/* 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);
|
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;
|
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));
|
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. */
|
/* 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));
|
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
|
#endif
|
||||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
|
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
|
||||||
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
|
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));
|
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 */
|
#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)
|
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_;
|
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));
|
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);
|
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));
|
+ 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;
|
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
||||||
compiler->local_size = local_size;
|
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)));
|
FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(options & SLJIT_ENTER_REG_ARG)) {
|
||||||
offset -= SSIZE_OF(sw);
|
offset -= SSIZE_OF(sw);
|
||||||
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
|
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
tmp = SLJIT_S0 - saveds;
|
tmp = SLJIT_S0 - saveds;
|
||||||
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
|
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)));
|
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));
|
FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
|
||||||
|
|
||||||
arg_types >>= SLJIT_ARG_SHIFT;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
|
saved_arg_count = 0;
|
||||||
|
|
||||||
while (arg_types > 0) {
|
while (arg_types > 0) {
|
||||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
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));
|
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);
|
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));
|
+ 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;
|
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
|
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
|
||||||
{
|
{
|
||||||
sljit_s32 i, tmp, base, offset;
|
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)));
|
FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
|
||||||
offset -= SSIZE_OF(sw);
|
offset -= SSIZE_OF(sw);
|
||||||
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
|
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
tmp = SLJIT_S0 - compiler->saveds;
|
tmp = SLJIT_S0 - compiler->saveds;
|
||||||
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
|
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);
|
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. */
|
/* Unlike or and xor, the and resets unwanted bits as well. */
|
||||||
if (TEST_UI_IMM(src2, src2w)) {
|
if (TEST_UI_IMM(src2, src2w)) {
|
||||||
compiler->imm = (sljit_ins)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_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
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);
|
return (4 << 21) | ((4 + 3) << 16);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
|
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
|
||||||
return (20 << 21);
|
return (20 << 21);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2186,6 +2199,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2194,11 +2208,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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)
|
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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);
|
return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
if (dst & SLJIT_MEM)
|
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, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
|
||||||
return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 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_ERROR();
|
||||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
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)
|
if (type & SLJIT_MEM_POST)
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
|
@ -2554,6 +2562,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
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)
|
if (type & SLJIT_MEM_POST)
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
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)
|
else if (local_size > 0)
|
||||||
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
|
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;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
|
saved_arg_count = 0;
|
||||||
tmp = SLJIT_R0;
|
tmp = SLJIT_R0;
|
||||||
|
|
||||||
while (arg_types > 0) {
|
while (arg_types > 0) {
|
||||||
|
@ -1727,10 +1731,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
|
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);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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;
|
type = SLJIT_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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)));
|
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;
|
arg_types >>= SLJIT_ARG_SHIFT;
|
||||||
|
saved_arg_count = 0;
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
while (arg_types > 0) {
|
while (arg_types > 0) {
|
||||||
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
|
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_ERROR();
|
||||||
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w);
|
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);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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;
|
type = SLJIT_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
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,8 +101,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
||||||
/* Calculate size of b. */
|
/* Calculate size of b. */
|
||||||
inst_size += 1; /* mod r/m byte. */
|
inst_size += 1; /* mod r/m byte. */
|
||||||
if (b & SLJIT_MEM) {
|
if (b & SLJIT_MEM) {
|
||||||
if (!(b & OFFS_REG_MASK)) {
|
if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
|
||||||
if (NOT_HALFWORD(immb)) {
|
|
||||||
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
|
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
|
||||||
immb = 0;
|
immb = 0;
|
||||||
if (b & REG_MASK)
|
if (b & REG_MASK)
|
||||||
|
@ -110,25 +109,30 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
||||||
else
|
else
|
||||||
b |= TMP_REG2;
|
b |= TMP_REG2;
|
||||||
}
|
}
|
||||||
else if (reg_lmap[b & REG_MASK] == 4)
|
|
||||||
b |= TO_OFFS_REG(SLJIT_SP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(b & REG_MASK))
|
if (!(b & REG_MASK))
|
||||||
inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
|
inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
|
||||||
else {
|
else {
|
||||||
if (reg_map[b & REG_MASK] >= 8)
|
if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||||
rex |= REX_B;
|
|
||||||
|
|
||||||
if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
|
|
||||||
/* Immediate operand. */
|
/* Immediate operand. */
|
||||||
if (immb <= 127 && immb >= -128)
|
if (immb <= 127 && immb >= -128)
|
||||||
inst_size += sizeof(sljit_s8);
|
inst_size += sizeof(sljit_s8);
|
||||||
else
|
else
|
||||||
inst_size += sizeof(sljit_s32);
|
inst_size += sizeof(sljit_s32);
|
||||||
}
|
}
|
||||||
else if (reg_lmap[b & REG_MASK] == 5)
|
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);
|
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) {
|
if (b & OFFS_REG_MASK) {
|
||||||
inst_size += 1; /* SIB byte. */
|
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) {
|
} else if (b & REG_MASK) {
|
||||||
reg_lmap_b = reg_lmap[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 != 0 || reg_lmap_b == 5) {
|
||||||
if (immb <= 127 && immb >= -128)
|
if (immb <= 127 && immb >= -128)
|
||||||
*buf_ptr |= 0x40;
|
*buf_ptr |= 0x40;
|
||||||
|
@ -248,8 +252,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (reg_lmap_b == 5)
|
||||||
|
*buf_ptr |= 0x40;
|
||||||
|
|
||||||
*buf_ptr++ |= 0x04;
|
*buf_ptr++ |= 0x04;
|
||||||
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
|
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
|
||||||
|
|
||||||
|
if (reg_lmap_b == 5)
|
||||||
|
*buf_ptr++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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));
|
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);
|
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. */
|
/* Emit ENDBR64 at function entry if needed. */
|
||||||
FAIL_IF(emit_endbranch(compiler));
|
FAIL_IF(emit_endbranch(compiler));
|
||||||
|
|
||||||
|
@ -786,6 +799,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
|
|
||||||
compiler->mode32 = 0;
|
compiler->mode32 = 0;
|
||||||
|
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
|
||||||
|
|
||||||
if (type & SLJIT_CALL_RETURN) {
|
if (type & SLJIT_CALL_RETURN) {
|
||||||
|
@ -793,10 +807,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
|
||||||
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_jump(compiler, type);
|
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));
|
FAIL_IF(emit_stack_frame_release(compiler));
|
||||||
type = SLJIT_JUMP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
|
||||||
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
FAIL_IF(call_with_args(compiler, arg_types, &src));
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
if (type & SLJIT_CALL_RETURN)
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
type = SLJIT_JUMP;
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
return sljit_emit_ijump(compiler, type, src, srcw);
|
return sljit_emit_ijump(compiler, type, src, srcw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,7 @@
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
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;
|
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) \
|
#define CHECK_EXTRA_REGS(p, w, do) \
|
||||||
if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
|
if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
|
||||||
if (p <= compiler->scratches) \
|
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 \
|
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); \
|
p = SLJIT_MEM1(SLJIT_SP); \
|
||||||
do; \
|
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));
|
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
|
||||||
|
|
||||||
if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
|
if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
|
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);
|
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
||||||
|
|
||||||
#else
|
#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)
|
if (GET_OPCODE(op) < SLJIT_ADD)
|
||||||
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
|
||||||
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
SLJIT_SKIP_CHECKS(compiler);
|
||||||
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
compiler->skip_checks = 1;
|
|
||||||
#endif
|
|
||||||
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
|
||||||
#endif /* SLJIT_CONFIG_X86_64 */
|
#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