update ares

This commit is contained in:
CasualPokePlayer 2022-08-10 04:42:38 -07:00
parent b1207b9c2c
commit b8444f8bd2
46 changed files with 8637 additions and 4016 deletions

Binary file not shown.

View File

@ -146,3 +146,38 @@ If you redistribute modified sources, we would appreciate that you include in
the file ChangeLog history information documenting your changes. Please read
the FAQ for more information on the distribution of modified source versions.
----------------------------------------------------------------------
----------------------------------------------------------------------
xxHash - Extremely Fast Hash algorithm
Header File
Copyright (C) 2012-2021 Yann Collet
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at:
- xxHash homepage: https://www.xxhash.com
- xxHash source repository: https://github.com/Cyan4973/xxHash

View File

@ -15,7 +15,7 @@ struct Accuracy {
static constexpr bool Recompiler = !Interpreter;
//VU instructions
static constexpr bool SISD = 0;// | Reference | !Architecture::amd64 | !Architecture::sse41;
static constexpr bool SISD = 0;// | Reference | !Architecture::sse41;
static constexpr bool SIMD = !SISD;
};

View File

@ -25,27 +25,32 @@ auto AI::unload() -> void {
}
auto AI::main() -> void {
sample();
f64 left = 0, right = 0;
sample(left, right);
stream->frame(left, right);
step(dac.period);
}
auto AI::sample() -> void {
if(io.dmaCount == 0) return stream->frame(0.0, 0.0);
auto AI::sample(f64& left, f64& right) -> void {
if(io.dmaCount == 0) return;
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
auto left = s16(data >> 16);
auto right = s16(data >> 0);
stream->frame(left / 32768.0, right / 32768.0);
if(io.dmaLength[0] && io.dmaEnable) {
io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry;
auto data = rdram.ram.read<Word>(io.dmaAddress[0]);
auto l = s16(data >> 16);
auto r = s16(data >> 0);
left = l / 32768.0;
right = r / 32768.0;
io.dmaAddress[0].bit(0,12) += 4;
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
io.dmaLength[0] -= 4;
io.dmaAddress[0].bit(0,12) += 4;
io.dmaAddressCarry = io.dmaAddress[0].bit(0,12) == 0;
io.dmaLength[0] -= 4;
}
if(!io.dmaLength[0]) {
mi.raise(MI::IRQ::AI);
if(--io.dmaCount) {
io.dmaAddress[0] = io.dmaAddress[1];
io.dmaLength [0] = io.dmaLength [1];
mi.raise(MI::IRQ::AI);
}
}
}

View File

@ -18,7 +18,7 @@ struct AI : Thread, Memory::IO<AI> {
auto load(Node::Object) -> void;
auto unload() -> void;
auto main() -> void;
auto sample() -> void;
auto sample(f64& left, f64& right) -> void;
auto step(u32 clocks) -> void;
auto power(bool reset) -> void;

View File

@ -12,6 +12,7 @@ auto AI::readWord(u32 address) -> u32 {
data.bit( 0) = io.dmaCount > 1;
data.bit(20) = 1;
data.bit(24) = 1;
data.bit(25) = io.dmaEnable;
data.bit(30) = io.dmaCount > 0;
data.bit(31) = io.dmaCount > 1;
}
@ -34,7 +35,8 @@ auto AI::writeWord(u32 address, u32 data_) -> void {
if(address == 1) {
//AI_LENGTH
n18 length = data.bit(0,17) & ~7;
if(io.dmaCount < 2 && length) {
if(io.dmaCount < 2) {
if(io.dmaCount == 0) mi.raise(MI::IRQ::AI);
io.dmaLength[io.dmaCount] = length;
io.dmaCount++;
}

View File

@ -4,7 +4,6 @@ namespace ares::Nintendo64 {
CPU cpu;
#include "context.cpp"
#include "icache.cpp"
#include "dcache.cpp"
#include "tlb.cpp"
#include "memory.cpp"

View File

@ -103,26 +103,80 @@ struct CPU : Thread {
//icache.cpp
struct InstructionCache {
CPU& self;
struct Line;
auto line(u32 address) -> Line&;
auto step(u32 address) -> void;
auto fetch(u32 address) -> u32;
auto read(u32 address) -> u32;
auto power(bool reset) -> void;
auto line(u32 address) -> Line& { return lines[address >> 5 & 0x1ff]; }
//used by the recompiler to simulate instruction cache fetch timing
auto step(u32 address) -> void {
auto& line = this->line(address);
if(!line.hit(address)) {
self.step(48);
line.valid = 1;
line.tag = address & ~0x0000'0fff;
} else {
self.step(2);
}
}
//used by the interpreter to fully emulate the instruction cache
auto fetch(u32 address, CPU& cpu) -> u32 {
auto& line = this->line(address);
if(!line.hit(address)) {
line.fill(address, cpu);
} else {
cpu.step(2);
}
return line.read(address);
}
auto power(bool reset) -> void {
u32 index = 0;
for(auto& line : lines) {
line.valid = 0;
line.tag = 0;
line.index = index++ << 5 & 0xfe0;
for(auto& word : line.words) word = 0;
}
}
//16KB
struct Line {
auto hit(u32 address) const -> bool;
auto fill(u32 address) -> void;
auto writeBack() -> void;
auto read(u32 address) const -> u32;
auto hit(u32 address) const -> bool { return valid && tag == (address & ~0x0000'0fff); }
auto fill(u32 address, CPU& cpu) -> void {
cpu.step(48);
valid = 1;
tag = address & ~0x0000'0fff;
words[0] = bus.read<Word>(tag | index | 0x00);
words[1] = bus.read<Word>(tag | index | 0x04);
words[2] = bus.read<Word>(tag | index | 0x08);
words[3] = bus.read<Word>(tag | index | 0x0c);
words[4] = bus.read<Word>(tag | index | 0x10);
words[5] = bus.read<Word>(tag | index | 0x14);
words[6] = bus.read<Word>(tag | index | 0x18);
words[7] = bus.read<Word>(tag | index | 0x1c);
}
auto writeBack(CPU& cpu) -> void {
cpu.step(48);
bus.write<Word>(tag | index | 0x00, words[0]);
bus.write<Word>(tag | index | 0x04, words[1]);
bus.write<Word>(tag | index | 0x08, words[2]);
bus.write<Word>(tag | index | 0x0c, words[3]);
bus.write<Word>(tag | index | 0x10, words[4]);
bus.write<Word>(tag | index | 0x14, words[5]);
bus.write<Word>(tag | index | 0x18, words[6]);
bus.write<Word>(tag | index | 0x1c, words[7]);
}
auto read(u32 address) const -> u32 { return words[address >> 2 & 7]; }
bool valid;
u32 tag;
u16 index;
u32 words[8];
} lines[512];
} icache;
} icache{*this};
//dcache.cpp
struct DataCache {
@ -705,12 +759,31 @@ struct CPU : Thread {
}
auto invalidate(u32 address) -> void {
/* FIXME: Recompiler shouldn't be so aggressive with pool eviction
* Sometimes there are overlapping blocks, so clearing just one block
* isn't sufficient and causes some games to crash (Jet Force Gemini)
* the recompiler needs to be smarter with block tracking
* Until then, clear the entire pool and live with the performance hit.
*/
#if 1
invalidatePool(address);
#else
auto pool = pools[address >> 8 & 0x1fffff];
if(!pool) return;
memory::jitprotect(false);
pool->blocks[address >> 2 & 0x3f] = nullptr;
memory::jitprotect(true);
#endif
}
auto invalidatePool(u32 address) -> void {
pools[address >> 8 & 0x1fffff] = nullptr;
}
auto invalidateRange(u32 address, u32 length) -> void {
for (u32 s = 0; s < length; s += 256)
invalidate(address + s);
invalidate(address + length - 1);
invalidatePool(address + s);
invalidatePool(address + length - 1);
}
auto pool(u32 address) -> Pool*;

View File

@ -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;
}
}

View File

@ -155,13 +155,13 @@ auto CPU::CACHE(u8 operation, cr64& rs, s16 imm) -> void {
case 0x14: { //icache fill
auto& line = icache.line(address);
line.fill(address);
line.fill(address, cpu);
break;
}
case 0x18: { //icache hit write back
auto& line = icache.line(address);
if(line.hit(address)) line.writeBack();
if(line.hit(address)) line.writeBack(cpu);
break;
}

View File

@ -114,7 +114,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
return 0; //nop
case Context::Segment::Mapped:
if(auto match = tlb.load(vaddr)) {
if(match.cache) return icache.fetch(match.address & context.physMask);
if(match.cache) return icache.fetch(match.address & context.physMask, cpu);
step(1);
return bus.read<Word>(match.address & context.physMask);
}
@ -122,7 +122,7 @@ auto CPU::fetch(u64 vaddr) -> u32 {
addressException(vaddr);
return 0; //nop
case Context::Segment::Cached:
return icache.fetch(vaddr & context.physMask);
return icache.fetch(vaddr & context.physMask, cpu);
case Context::Segment::Direct:
step(1);
return bus.read<Word>(vaddr & context.physMask);

View File

@ -115,6 +115,7 @@ auto CPU::serialize(serializer& s) -> void {
s(scc.tagLo.primaryCacheState);
s(scc.tagLo.physicalAddress);
s(scc.epcError);
s(scc.latch);
for(auto& r : fpu.r) s(r.u64);
s(fpu.csr.roundMode);

View File

@ -1,6 +1,8 @@
#pragma once
//started: 2020-04-28
#define XXH_INLINE_ALL
#include <xxhash.h>
#include <ares/ares.hpp>
#include <nall/hashset.hpp>
#include <nall/recompiler/generic/generic.hpp>
@ -9,6 +11,9 @@
#if defined(ARCHITECTURE_AMD64)
#include <nmmintrin.h>
using v128 = __m128i;
#elif defined(ARCHITECTURE_ARM64)
#include <sse2neon.h>
using v128 = __m128i;
#endif
#if defined(VULKAN)

View File

@ -37,7 +37,7 @@ auto PI::dmaWrite() -> void {
}
if constexpr(Accuracy::CPU::Recompiler) {
cpu.recompiler.invalidateRange(io.dramAddress, io.dramAddress + cur_len);
cpu.recompiler.invalidateRange(io.dramAddress, cur_len);
}
for (u32 i = 0; i < cur_len; i++)
rdram.ram.write<Byte>(io.dramAddress++, mem[i]);

View File

@ -50,9 +50,7 @@ auto RDP::render() -> void {
#endif
#if defined(ANGRYLION_RDP)
if (angrylion::ProcessRDPList()) {
command.start = command.current = command.end;
}
command.current = angrylion::ProcessRDPList();
return;
#endif

View File

@ -11,6 +11,9 @@ auto RDP::serialize(serializer& s) -> void {
s(command.source);
s(command.freeze);
s(command.flush);
s(command.startValid);
s(command.endValid);
s(command.startGclk);
s(command.ready);
s(io.bist.check);

View File

@ -12,10 +12,11 @@ auto RSP::dmaTransferStep() -> void {
auto& region = !dma.current.pbusRegion ? dmem : imem;
if(dma.busy.read) {
if constexpr(Accuracy::RSP::Recompiler) {
if(dma.current.pbusRegion) recompiler.invalidate();
}
for(u32 i = 0; i <= dma.current.length; i += 8) {
if constexpr(Accuracy::RSP::Recompiler) {
if(dma.current.pbusRegion) recompiler.invalidate(dma.current.pbusAddress);
}
u64 data = rdram.ram.read<Dual>(dma.current.dramAddress);
region.write<Dual>(dma.current.pbusAddress, data);
dma.current.dramAddress += 8;

View File

@ -36,7 +36,6 @@ auto RSP::r128::operator()(u32 index) const -> r128 {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
static const __m128i shuffle[16] = {
//vector
_mm_set_epi8(15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), //01234567
@ -61,7 +60,6 @@ auto RSP::r128::operator()(u32 index) const -> r128 {
};
//todo: benchmark to see if testing for cases 0&1 to return value directly is faster
return {uint128_t(_mm_shuffle_epi8(v128, shuffle[index]))};
#endif
}
}
@ -105,10 +103,8 @@ auto RSP::CFC2(r32& rt, u8 rd) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
static const v128 reverse = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
rt.u32 = s16(_mm_movemask_epi8(_mm_shuffle_epi8(_mm_packs_epi16(hi, lo), reverse)));
#endif
}
}
@ -130,11 +126,9 @@ auto RSP::CTC2(cr32& rt, u8 rd) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
static const v128 mask = _mm_set_epi16(0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080);
lo->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 0}, zero), mask), zero);
hi->v128 = _mm_cmpeq_epi8(_mm_and_si128(_mm_shuffle_epi8(r128{~rt.u32 >> 8}, zero), mask), zero);
#endif
}
}
@ -487,7 +481,6 @@ auto RSP::VABS(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vs0, slt;
vs0 = _mm_cmpeq_epi16(vs, zero);
slt = _mm_srai_epi16(vs, 15);
@ -495,7 +488,6 @@ auto RSP::VABS(r128& vd, cr128& vs, cr128& vt) -> void {
vd = _mm_xor_si128(vd, slt);
ACCL = _mm_sub_epi16(vd, slt);
vd = _mm_subs_epi16(vd, slt);
#endif
}
}
@ -513,7 +505,6 @@ auto RSP::VADD(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sum, min, max;
sum = _mm_add_epi16(vs, vte);
ACCL = _mm_sub_epi16(sum, VCOL);
@ -523,7 +514,6 @@ auto RSP::VADD(r128& vd, cr128& vs, cr128& vt) -> void {
vd = _mm_adds_epi16(min, max);
VCOL = zero;
VCOH = zero;
#endif
}
}
@ -541,7 +531,6 @@ auto RSP::VADDC(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sum;
sum = _mm_adds_epu16(vs, vte);
ACCL = _mm_add_epi16(vs, vte);
@ -549,7 +538,6 @@ auto RSP::VADDC(r128& vd, cr128& vs, cr128& vt) -> void {
VCOL = _mm_cmpeq_epi16(VCOL, zero);
VCOH = zero;
vd = ACCL;
#endif
}
}
@ -564,10 +552,8 @@ auto RSP::VAND(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_and_si128(vs, vt(e));
vd = ACCL;
#endif
}
}
@ -598,7 +584,6 @@ auto RSP::VCH(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), nvt, diff, diff0, vtn, dlez, dgez, mask;
VCOL = _mm_xor_si128(vs, vte);
VCOL = _mm_cmplt_epi16(VCOL, zero);
@ -619,7 +604,6 @@ auto RSP::VCH(r128& vd, cr128& vs, cr128& vt) -> void {
mask = _mm_blendv_epi8(VCCH, VCCL, VCOL);
ACCL = _mm_blendv_epi8(vs, nvt, mask);
vd = ACCL;
#endif
}
}
@ -655,7 +639,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), nvt, diff, ncarry, nvce, diff0, lec1, lec2, leeq, geeq, le, ge, mask;
nvt = _mm_xor_si128(vte, VCOL);
nvt = _mm_sub_epi16(nvt, VCOL);
@ -683,7 +666,6 @@ auto RSP::VCL(r128& vd, cr128& vs, cr128& vt) -> void {
VCOL = zero;
VCE = zero;
vd = ACCL;
#endif
}
}
@ -707,7 +689,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sign, dlez, dgez, nvt, mask;
sign = _mm_xor_si128(vs, vte);
sign = _mm_srai_epi16(sign, 15);
@ -724,7 +705,6 @@ auto RSP::VCR(r128& vd, cr128& vs, cr128& vt) -> void {
VCOL = zero;
VCOH = zero;
VCE = zero;
#endif
}
}
@ -742,7 +722,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), eq;
eq = _mm_cmpeq_epi16(vs, vte);
VCCL = _mm_andnot_si128(VCOH, eq);
@ -751,7 +730,6 @@ auto RSP::VEQ(r128& vd, cr128& vs, cr128& vt) -> void {
VCOH = zero;
VCOL = zero;
vd = ACCL;
#endif
}
}
@ -769,7 +747,6 @@ auto RSP::VGE(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), eq, gt, es;
eq = _mm_cmpeq_epi16(vs, vte);
gt = _mm_cmpgt_epi16(vs, vte);
@ -781,7 +758,6 @@ auto RSP::VGE(r128& vd, cr128& vs, cr128& vt) -> void {
VCOH = zero;
VCOL = zero;
vd = ACCL;
#endif
}
}
@ -799,7 +775,6 @@ auto RSP::VLT(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), eq, lt;
eq = _mm_cmpeq_epi16(vs, vte);
lt = _mm_cmplt_epi16(vs, vte);
@ -811,7 +786,6 @@ auto RSP::VLT(r128& vd, cr128& vs, cr128& vt) -> void {
VCOH = zero;
VCOL = zero;
vd = ACCL;
#endif
}
}
@ -831,7 +805,6 @@ auto RSP::VMACF(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, md, hi, carry, omask;
lo = _mm_mullo_epi16(vs, vte);
hi = _mm_mulhi_epi16(vs, vte);
@ -867,7 +840,6 @@ auto RSP::VMACF(r128& vd, cr128& vs, cr128& vt) -> void {
md = _mm_andnot_si128(hmask, md);
vd = _mm_or_si128(omask, md);
}
#endif
}
}
@ -895,7 +867,6 @@ auto RSP::VMADH(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, hi, omask;
lo = _mm_mullo_epi16(vs, vte);
hi = _mm_mulhi_epi16(vs, vte);
@ -908,7 +879,6 @@ auto RSP::VMADH(r128& vd, cr128& vs, cr128& vt) -> void {
lo = _mm_unpacklo_epi16(ACCM, ACCH);
hi = _mm_unpackhi_epi16(ACCM, ACCH);
vd = _mm_packs_epi32(lo, hi);
#endif
}
}
@ -923,7 +893,6 @@ auto RSP::VMADL(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), hi, omask, nhi, nmd, shi, smd, cmask, cval;
hi = _mm_mulhi_epu16(vs, vte);
omask = _mm_adds_epu16(ACCL, hi);
@ -943,7 +912,6 @@ auto RSP::VMADL(r128& vd, cr128& vs, cr128& vt) -> void {
cmask = _mm_and_si128(smd, shi);
cval = _mm_cmpeq_epi16(nhi, zero);
vd = _mm_blendv_epi8(cval, ACCL, cmask);
#endif
}
}
@ -958,7 +926,6 @@ auto RSP::VMADM(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, hi, sign, vta, omask;
lo = _mm_mullo_epi16(vs, vte);
hi = _mm_mulhi_epu16(vs, vte);
@ -980,7 +947,6 @@ auto RSP::VMADM(r128& vd, cr128& vs, cr128& vt) -> void {
lo = _mm_unpacklo_epi16(ACCM, ACCH);
hi = _mm_unpackhi_epi16(ACCM, ACCH);
vd = _mm_packs_epi32(lo, hi);
#endif
}
}
@ -995,7 +961,6 @@ auto RSP::VMADN(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, hi, sign, vsa, omask, nhi, nmd, shi, smd, cmask, cval;
lo = _mm_mullo_epi16(vs, vte);
hi = _mm_mulhi_epu16(vs, vte);
@ -1021,7 +986,6 @@ auto RSP::VMADN(r128& vd, cr128& vs, cr128& vt) -> void {
cmask = _mm_and_si128(smd, shi);
cval = _mm_cmpeq_epi16(nhi, zero);
vd = _mm_blendv_epi8(cval, ACCL, cmask);
#endif
}
}
@ -1045,12 +1009,10 @@ auto RSP::VMRG(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_blendv_epi8(vt(e), vs, VCCL);
VCOH = zero;
VCOL = zero;
vd = ACCL;
#endif
}
}
@ -1065,7 +1027,6 @@ auto RSP::VMUDH(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, hi;
ACCL = zero;
ACCM = _mm_mullo_epi16(vs, vte);
@ -1073,7 +1034,6 @@ auto RSP::VMUDH(r128& vd, cr128& vs, cr128& vt) -> void {
lo = _mm_unpacklo_epi16(ACCM, ACCH);
hi = _mm_unpackhi_epi16(ACCM, ACCH);
vd = _mm_packs_epi32(lo, hi);
#endif
}
}
@ -1088,12 +1048,10 @@ auto RSP::VMUDL(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_mulhi_epu16(vs, vt(e));
ACCM = zero;
ACCH = zero;
vd = ACCL;
#endif
}
}
@ -1108,7 +1066,6 @@ auto RSP::VMUDM(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sign, vta;
ACCL = _mm_mullo_epi16(vs, vte);
ACCM = _mm_mulhi_epu16(vs, vte);
@ -1117,7 +1074,6 @@ auto RSP::VMUDM(r128& vd, cr128& vs, cr128& vt) -> void {
ACCM = _mm_sub_epi16(ACCM, vta);
ACCH = _mm_srai_epi16(ACCM, 15);
vd = ACCM;
#endif
}
}
@ -1132,7 +1088,6 @@ auto RSP::VMUDN(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sign, vsa;
ACCL = _mm_mullo_epi16(vs, vte);
ACCM = _mm_mulhi_epu16(vs, vte);
@ -1141,7 +1096,6 @@ auto RSP::VMUDN(r128& vd, cr128& vs, cr128& vt) -> void {
ACCM = _mm_sub_epi16(ACCM, vsa);
ACCH = _mm_srai_epi16(ACCM, 15);
vd = ACCL;
#endif
}
}
@ -1161,7 +1115,6 @@ auto RSP::VMULF(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), lo, hi, round, sign1, sign2, neq, eq, neg;
lo = _mm_mullo_epi16(vs, vte);
round = _mm_cmpeq_epi16(zero, zero);
@ -1185,7 +1138,6 @@ auto RSP::VMULF(r128& vd, cr128& vs, cr128& vt) -> void {
hi = _mm_or_si128(ACCM, neg);
vd = _mm_andnot_si128(ACCH, hi);
}
#endif
}
}
@ -1213,11 +1165,9 @@ auto RSP::VNAND(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_and_si128(vs, vt(e));
ACCL = _mm_xor_si128(ACCL, invert);
vd = ACCL;
#endif
}
}
@ -1235,7 +1185,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), eq, ne;
eq = _mm_cmpeq_epi16(vs, vte);
ne = _mm_cmpeq_epi16(eq, zero);
@ -1246,7 +1195,6 @@ auto RSP::VNE(r128& vd, cr128& vs, cr128& vt) -> void {
VCOH = zero;
VCOL = zero;
vd = ACCL;
#endif
}
}
@ -1264,11 +1212,9 @@ auto RSP::VNOR(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_or_si128(vs, vt(e));
ACCL = _mm_xor_si128(ACCL, invert);
vd = ACCL;
#endif
}
}
@ -1283,11 +1229,9 @@ auto RSP::VNXOR(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_xor_si128(vs, vt(e));
ACCL = _mm_xor_si128(ACCL, invert);
vd = ACCL;
#endif
}
}
@ -1302,10 +1246,8 @@ auto RSP::VOR(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_or_si128(vs, vt(e));
vd = ACCL;
#endif
}
}
@ -1417,7 +1359,6 @@ auto RSP::VSUB(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), udiff, sdiff, ov;
udiff = _mm_sub_epi16(vte, VCOL);
sdiff = _mm_subs_epi16(vte, VCOL);
@ -1427,7 +1368,6 @@ auto RSP::VSUB(r128& vd, cr128& vs, cr128& vt) -> void {
vd = _mm_adds_epi16(vd, ov);
VCOL = zero;
VCOH = zero;
#endif
}
}
@ -1445,7 +1385,6 @@ auto RSP::VSUBC(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), equal, udiff, diff0;
udiff = _mm_subs_epu16(vs, vte);
equal = _mm_cmpeq_epi16(vs, vte);
@ -1454,7 +1393,6 @@ auto RSP::VSUBC(r128& vd, cr128& vs, cr128& vt) -> void {
VCOL = _mm_andnot_si128(equal, diff0);
ACCL = _mm_sub_epi16(vs, vte);
vd = ACCL;
#endif
}
}
@ -1469,10 +1407,8 @@ auto RSP::VXOR(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
ACCL = _mm_xor_si128(vs, vt(e));
vd = ACCL;
#endif
}
}
@ -1488,11 +1424,9 @@ auto RSP::VZERO(r128& vd, cr128& vs, cr128& vt) -> void {
}
if constexpr(Accuracy::RSP::SIMD) {
#if defined(ARCHITECTURE_AMD64)
r128 vte = vt(e), sum, min, max;
ACCL = _mm_add_epi16(vs, vte);
vd = _mm_xor_si128(vd, vd);
#endif
}
}

View File

@ -69,7 +69,7 @@ auto RSP::ioRead(u32 address) -> u32 {
auto RSP::writeWord(u32 address, u32 data) -> void {
if(address <= 0x0403'ffff) {
if(address & 0x1000) return recompiler.invalidate(), imem.write<Word>(address, data);
if(address & 0x1000) return recompiler.invalidate(address & 0xfff), imem.write<Word>(address, data);
else return dmem.write<Word>(address, data);
}
return ioWrite(address, data);

View File

@ -1,35 +1,34 @@
auto RSP::Recompiler::pool() -> Pool* {
if(context) return context;
auto RSP::Recompiler::pool(u12 address) -> Pool* {
if(context[address >> 8]) return context[address >> 8];
nall::Hash::CRC32 hashcode;
for(u32 offset : range(4096)) {
hashcode.input(self.imem.read<Byte>(offset));
}
auto hashcode = XXH3_64bits(self.imem.data + address, 256);
PoolHashPair pair;
pair.pool = (Pool*)allocator.acquire();
pair.hashcode = hashcode.value();
if(auto result = pools.find(pair)) {
return context = result->pool;
pair.hashcode = hashcode;
auto result = pools[address >> 8].find(pair);
if(result) {
return context[address >> 8] = result->pool;
}
allocator.reserve(sizeof(Pool));
if(auto result = pools.insert(pair)) {
return context = result->pool;
if(auto result = pools[address >> 8].insert(pair)) {
return context[address >> 8] = result->pool;
}
throw; //should never occur
}
auto RSP::Recompiler::block(u32 address) -> Block* {
if(auto block = pool()->blocks[address >> 2 & 0x3ff]) return block;
auto RSP::Recompiler::block(u12 address) -> Block* {
if(auto block = pool(address)->blocks[address >> 2 & 0x3ff]) return block;
auto block = emit(address);
pool()->blocks[address >> 2 & 0x3ff] = block;
pool(address)->blocks[address >> 2 & 0x3ff] = block;
memory::jitprotect(true);
return block;
}
auto RSP::Recompiler::emit(u32 address) -> Block* {
auto RSP::Recompiler::emit(u12 address) -> Block* {
if(unlikely(allocator.available() < 1_MiB)) {
print("RSP allocator flush\n");
memory::jitprotect(false);

View File

@ -108,7 +108,7 @@ struct RSP : Thread, Memory::IO<RSP> {
};
r32 r[32];
u12 pc;
u16 pc; // previously u12; now u16 for performance.
} ipu;
struct Branch {
@ -175,7 +175,7 @@ struct RSP : Thread, Memory::IO<RSP> {
//vpu.cpp: Vector Processing Unit
union r128 {
struct { uint128_t u128; };
#if defined(ARCHITECTURE_AMD64)
#if defined(ARCHITECTURE_AMD64) || defined(ARCHITECTURE_ARM64)
struct { __m128i v128; };
operator __m128i() const { return v128; }
@ -350,18 +350,18 @@ struct RSP : Thread, Memory::IO<RSP> {
};
auto reset() -> void {
context = nullptr;
pools.reset();
for(auto n : range(16)) context[n] = nullptr;
for(auto n : range(16)) pools[n].reset();
}
auto invalidate() -> void {
context = nullptr;
auto invalidate(u32 address) -> void {
context[address >> 8] = nullptr;
}
auto pool() -> Pool*;
auto block(u32 address) -> Block*;
auto pool(u12 address) -> Pool*;
auto block(u12 address) -> Block*;
auto emit(u32 address) -> Block*;
auto emit(u12 address) -> Block*;
auto emitEXECUTE(u32 instruction) -> bool;
auto emitSPECIAL(u32 instruction) -> bool;
auto emitREGIMM(u32 instruction) -> bool;
@ -371,9 +371,8 @@ struct RSP : Thread, Memory::IO<RSP> {
auto emitSWC2(u32 instruction) -> bool;
bump_allocator allocator;
Pool* context = nullptr;
set<PoolHashPair> pools;
//hashset<PoolHashPair> pools;
Pool* context[16];
set<PoolHashPair> pools[16];
} recompiler{*this};
struct Disassembler {

View File

@ -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

View File

@ -199,7 +199,7 @@ namespace nall {
struct Architecture {
static constexpr bool x86 = 0;
static constexpr bool amd64 = 0;
static constexpr bool sse41 = 0;
static constexpr bool sse41 = 1; // simulated via sse2neon.h
static constexpr bool arm64 = 1;
static constexpr bool arm32 = 0;
static constexpr bool ppc64 = 0;

@ -1 +1 @@
Subproject commit fd4173287f22271908b82148470e4e1e34707228
Subproject commit 5dc6921aba40fcc94e9578e93a16ab8ba402d0f8

View File

@ -1,5 +1,9 @@
This file is the short summary of the API changes:
16.06.2022 - Non-backward compatible
Remove SLJIT_ENTER_CDECL and SLJIT_CALL_CDECL.
The default calling mode is cdecl now.
21.04.2022 - Non-backward compatible
Floating point comparison types are renamed.

View File

@ -36,7 +36,7 @@ SLJIT_LIR_FILES = $(SRCDIR)/sljitLir.c $(SRCDIR)/sljitUtils.c \
$(SRCDIR)/sljitNativeARM_32.c $(SRCDIR)/sljitNativeARM_T2_32.c $(SRCDIR)/sljitNativeARM_64.c \
$(SRCDIR)/sljitNativeMIPS_common.c $(SRCDIR)/sljitNativeMIPS_32.c $(SRCDIR)/sljitNativeMIPS_64.c \
$(SRCDIR)/sljitNativePPC_common.c $(SRCDIR)/sljitNativePPC_32.c $(SRCDIR)/sljitNativePPC_64.c \
$(SRCDIR)/sljitNativeSPARC_common.c $(SRCDIR)/sljitNativeSPARC_32.c \
$(SRCDIR)/sljitNativeRISCV_common.c $(SRCDIR)/sljitNativeRISCV_32.c $(SRCDIR)/sljitNativeRISCV_64.c \
$(SRCDIR)/sljitNativeS390X.c \
$(SRCDIR)/sljitNativeX86_common.c $(SRCDIR)/sljitNativeX86_32.c $(SRCDIR)/sljitNativeX86_64.c

View File

@ -53,7 +53,8 @@ extern "C" {
/* #define SLJIT_CONFIG_PPC_64 1 */
/* #define SLJIT_CONFIG_MIPS_32 1 */
/* #define SLJIT_CONFIG_MIPS_64 1 */
/* #define SLJIT_CONFIG_SPARC_32 1 */
/* #define SLJIT_CONFIG_RISCV_32 1 */
/* #define SLJIT_CONFIG_RISCV_64 1 */
/* #define SLJIT_CONFIG_S390X 1 */
/* #define SLJIT_CONFIG_AUTO 1 */
@ -127,17 +128,6 @@ extern "C" {
#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
/* Force cdecl calling convention even if a better calling
convention (e.g. fastcall) is supported by the C compiler.
If this option is disabled (this is the default), functions
called from JIT should be defined with SLJIT_FUNC attribute.
Standard C functions can still be called by using the
SLJIT_CALL_CDECL jump type. */
#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
/* Disabled by default */
#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
#endif
/* Return with error when an invalid argument is passed. */
#ifndef SLJIT_ARGUMENT_CHECKS
/* Disabled by default */

View File

@ -59,7 +59,8 @@ extern "C" {
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
SLJIT_LITTLE_ENDIAN : little endian architecture
SLJIT_BIG_ENDIAN : big endian architecture
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported
SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
Constants:
@ -100,7 +101,6 @@ extern "C" {
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
+ (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+ (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
@ -119,7 +119,6 @@ extern "C" {
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
&& !(defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
@ -164,8 +163,6 @@ extern "C" {
#define SLJIT_CONFIG_RISCV_32 1
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
#define SLJIT_CONFIG_RISCV_64 1
#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64)
#define SLJIT_CONFIG_SPARC_32 1
#elif defined(__s390x__)
#define SLJIT_CONFIG_S390X 1
#else
@ -215,8 +212,6 @@ extern "C" {
#define SLJIT_CONFIG_MIPS 1
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
#define SLJIT_CONFIG_RISCV 1
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
#define SLJIT_CONFIG_SPARC 1
#endif
/***********************************************************/
@ -355,9 +350,9 @@ extern "C" {
/*
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
* gcc's clear_cache builtin for power and sparc are broken
* gcc's clear_cache builtin for power is broken
*/
#if !defined(SLJIT_CONFIG_PPC) && !defined(SLJIT_CONFIG_SPARC_32)
#if !defined(SLJIT_CONFIG_PPC)
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
#endif
@ -389,13 +384,6 @@ extern "C" {
ppc_cache_flush((from), (to))
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
#define SLJIT_CACHE_FLUSH(from, to) \
sparc_cache_flush((from), (to))
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
#elif defined(_WIN32)
#define SLJIT_CACHE_FLUSH(from, to) \
@ -512,8 +500,7 @@ typedef double sljit_f64;
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
/* These macros are mostly useful for the applications. */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#ifdef __LITTLE_ENDIAN__
#define SLJIT_LITTLE_ENDIAN 1
@ -521,8 +508,7 @@ typedef double sljit_f64;
#define SLJIT_BIG_ENDIAN 1
#endif
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
#ifdef __MIPSEL__
#define SLJIT_LITTLE_ENDIAN 1
@ -549,8 +535,7 @@ typedef double sljit_f64;
#endif /* !SLJIT_MIPS_REV */
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
#define SLJIT_BIG_ENDIAN 1
@ -583,6 +568,18 @@ typedef double sljit_f64;
#endif /* !SLJIT_UNALIGNED */
#ifndef SLJIT_FPU_UNALIGNED
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
#define SLJIT_FPU_UNALIGNED 1
#endif
#endif /* !SLJIT_FPU_UNALIGNED */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
/* Auto detect SSE2 support using CPUID.
On 64 bit x86 cpus, sse2 must be present. */
@ -594,38 +591,7 @@ typedef double sljit_f64;
/*****************************************************************************************/
#ifndef SLJIT_FUNC
#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \
|| !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#define SLJIT_FUNC
#elif defined(__GNUC__) && !defined(__APPLE__)
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define SLJIT_FUNC __attribute__ ((fastcall))
#define SLJIT_X86_32_FASTCALL 1
#else
#define SLJIT_FUNC
#endif /* gcc >= 3.4 */
#elif defined(_MSC_VER)
#define SLJIT_FUNC __fastcall
#define SLJIT_X86_32_FASTCALL 1
#elif defined(__BORLANDC__)
#define SLJIT_FUNC __msfastcall
#define SLJIT_X86_32_FASTCALL 1
#else /* Unknown compiler. */
/* The cdecl calling convention is usually the x86 default. */
#define SLJIT_FUNC
#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */
#endif /* !SLJIT_FUNC */
#ifndef SLJIT_INDIRECT_CALL
@ -640,11 +606,7 @@ typedef double sljit_f64;
/* The offset which needs to be substracted from the return address to
determine the next executed instruction after return. */
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_RETURN_ADDRESS_OFFSET 8
#else
#define SLJIT_RETURN_ADDRESS_OFFSET 0
#endif
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
/***************************************************/
@ -682,10 +644,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw))
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@ -699,7 +661,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#else /* _WIN64 */
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw))
#endif /* !_WIN64 */
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
@ -764,18 +726,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
#define SLJIT_NUMBER_OF_REGISTERS 18
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
/* saved registers (16), return struct pointer (1), space for 6 argument words (1),
4th double arg (2), double alignment (1). */
#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * (sljit_s32)sizeof(sljit_sw))
#endif
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/*
@ -831,7 +781,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|| (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
#endif

View File

@ -148,16 +148,16 @@
# define PATCH_MD 0x10
#endif
# define TYPE_SHIFT 13
#endif
#endif /* SLJIT_CONFIG_X86 */
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
# define IS_BL 0x4
# define PATCH_B 0x8
#endif
#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
# define CPOOL_SIZE 512
#endif
#endif /* SLJIT_CONFIG_ARM_V5 */
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
# define IS_COND 0x04
@ -175,7 +175,7 @@
/* BL + imm24 */
# define PATCH_BL 0x60
/* 0xf00 cc code for branches */
#endif
#endif /* SLJIT_CONFIG_ARM_THUMB2 */
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
# define IS_COND 0x004
@ -185,7 +185,7 @@
# define PATCH_COND 0x040
# define PATCH_ABS48 0x080
# define PATCH_ABS64 0x100
#endif
#endif /* SLJIT_CONFIG_ARM_64 */
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
# define IS_COND 0x004
@ -195,9 +195,9 @@
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
# define PATCH_ABS32 0x040
# define PATCH_ABS48 0x080
#endif
#endif /* SLJIT_CONFIG_PPC_64 */
# define REMOVE_COND 0x100
#endif
#endif /* SLJIT_CONFIG_PPC */
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
# define IS_MOVABLE 0x004
@ -215,7 +215,7 @@
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
# define PATCH_ABS32 0x400
# define PATCH_ABS48 0x800
#endif
#endif /* SLJIT_CONFIG_MIPS_64 */
/* instruction types */
# define MOVABLE_INS 0
@ -224,7 +224,7 @@
# define UNMOVABLE_INS 32
/* FPU status register */
# define FCSR_FCC 33
#endif
#endif /* SLJIT_CONFIG_MIPS */
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
# define IS_COND 0x004
@ -241,28 +241,7 @@
#else /* !SLJIT_CONFIG_RISCV_64 */
# define PATCH_REL32 0x0
#endif /* SLJIT_CONFIG_RISCV_64 */
#endif
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
# define IS_MOVABLE 0x04
# define IS_COND 0x08
# define IS_CALL 0x10
# define PATCH_B 0x20
# define PATCH_CALL 0x40
/* instruction types */
# define MOVABLE_INS 0
/* 1 - 31 last destination register */
/* no destination (i.e: store) */
# define UNMOVABLE_INS 32
# define DST_INS_MASK 0xff
/* ICC_SET is the same as SET_FLAGS. */
# define ICC_IS_SET (1 << 23)
# define FCC_IS_SET (1 << 24)
#endif
#endif /* SLJIT_CONFIG_RISCV */
/* Stack management. */
@ -457,10 +436,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
compiler->delay_slot = UNMOVABLE_INS;
#endif
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
compiler->delay_slot = UNMOVABLE_INS;
#endif
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->last_flags = 0;
@ -842,6 +817,9 @@ static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s
if (!(p & SLJIT_MEM))
return 0;
if (p == SLJIT_MEM1(SLJIT_SP))
return (i >= 0 && i < compiler->logical_local_size);
if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
return 0;
@ -879,9 +857,6 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p
if (p == SLJIT_IMM)
return 1;
if (p == SLJIT_MEM1(SLJIT_SP))
return (i >= 0 && i < compiler->logical_local_size);
return function_check_src_mem(compiler, p, i);
}
@ -896,9 +871,6 @@ static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p
if (FUNCTION_CHECK_IS_REG(p))
return (i == 0);
if (p == SLJIT_MEM1(SLJIT_SP))
return (i >= 0 && i < compiler->logical_local_size);
return function_check_src_mem(compiler, p, i);
}
@ -913,9 +885,6 @@ static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, s
if (FUNCTION_CHECK_IS_FREG(p))
return (i == 0);
if (p == SLJIT_MEM1(SLJIT_SP))
return (i >= 0 && i < compiler->logical_local_size);
return function_check_src_mem(compiler, p, i);
}
@ -1063,7 +1032,7 @@ static const char* jump_names[] = {
"unordered_or_less", "ordered_greater_equal",
"unordered_or_greater", "ordered_less_equal",
"jump", "fast_call",
"call", "call.cdecl"
"call", "call_reg_arg"
};
static const char* call_arg_names[] = {
@ -1079,6 +1048,8 @@ static const char* call_arg_names[] = {
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@ -1106,8 +1077,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
if (options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
} else {
CHECK_ARGUMENT(options == 0);
}
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
@ -1116,7 +1091,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), fscratches));
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
compiler->last_flags = 0;
#endif
@ -1138,10 +1113,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
fprintf(compiler->verbose, "],");
if (options & SLJIT_ENTER_CDECL)
fprintf(compiler->verbose, " enter:cdecl,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
if (options & SLJIT_ENTER_REG_ARG) {
fprintf(compiler->verbose, " enter:reg_arg,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
}
fprintf(compiler->verbose, "scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
scratches, saveds, fscratches, fsaveds, local_size);
@ -1157,8 +1134,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(options & ~(SLJIT_ENTER_KEEP_S0 | SLJIT_ENTER_KEEP_S0_S1 | SLJIT_ENTER_CDECL)));
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 2 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
if (options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG)));
} else {
CHECK_ARGUMENT(options == 0);
}
CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
@ -1167,7 +1148,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), fscratches));
CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, (options & SLJIT_ENTER_REG_ARG) ? 0 : saveds, fscratches));
compiler->last_flags = 0;
#endif
@ -1189,10 +1170,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
fprintf(compiler->verbose, "],");
if (options & SLJIT_ENTER_CDECL)
fprintf(compiler->verbose, " enter:cdecl,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
if (options & SLJIT_ENTER_REG_ARG) {
fprintf(compiler->verbose, " enter:reg_arg,");
if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
fprintf(compiler->verbose, " keep:%d,", SLJIT_KEPT_SAVEDS_COUNT(options));
}
fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
scratches, saveds, fscratches, fsaveds, local_size);
@ -1737,11 +1720,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
if (type & SLJIT_CALL_RETURN) {
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
if (compiler->options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
} else {
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
}
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@ -1845,12 +1834,18 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
FUNCTION_CHECK_SRC(src, srcw);
if (type & SLJIT_CALL_RETURN) {
CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
if (compiler->options & SLJIT_ENTER_REG_ARG) {
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
} else {
CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
}
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@ -1954,27 +1949,63 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
sljit_s32 mem, sljit_sw memw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
sljit_s32 allowed_flags;
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));
if (type & SLJIT_MEM_UNALIGNED) {
allowed_flags = SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32;
switch (type & 0xff) {
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
allowed_flags = 0;
break;
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
case SLJIT_MOV32:
allowed_flags = SLJIT_MEM_ALIGNED_16;
break;
}
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | allowed_flags)) == 0);
CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32));
} else {
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
}
FUNCTION_CHECK_SRC_MEM(mem, memw);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
fprintf(compiler->verbose, " //");
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
if (type & SLJIT_MEM_SUPP)
CHECK_RETURN_OK;
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " // mem: unsupported form, no instructions are emitted");
CHECK_RETURN_OK;
}
}
fprintf(compiler->verbose, " mem%s.%s%s%s ",
!(type & SLJIT_32) ? "" : "32",
(type & SLJIT_MEM_STORE) ? "st" : "ld",
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
if ((type & 0xff) == SLJIT_MOV32)
fprintf(compiler->verbose, " mem32.%s",
(type & SLJIT_MEM_STORE) ? "st" : "ld");
else
fprintf(compiler->verbose, " mem%s.%s%s",
!(type & SLJIT_32) ? "" : "32",
(type & SLJIT_MEM_STORE) ? "st" : "ld",
op1_names[(type & 0xff) - SLJIT_OP1_BASE]);
if (type & SLJIT_MEM_UNALIGNED) {
printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : "");
} else
printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post ");
sljit_verbose_reg(compiler, reg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, mem, memw);
@ -1990,22 +2021,37 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
if (type & SLJIT_MEM_UNALIGNED) {
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | (type & SLJIT_32 ? 0 : SLJIT_MEM_ALIGNED_32))) == 0);
CHECK_ARGUMENT((type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) != (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32));
} else {
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
}
FUNCTION_CHECK_SRC_MEM(mem, memw);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
fprintf(compiler->verbose, " //");
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) {
if (type & SLJIT_MEM_SUPP)
CHECK_RETURN_OK;
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
fprintf(compiler->verbose, " // fmem: unsupported form, no instructions are emitted");
CHECK_RETURN_OK;
}
}
fprintf(compiler->verbose, " fmem.%s%s%s ",
fprintf(compiler->verbose, " fmem.%s%s",
(type & SLJIT_MEM_STORE) ? "st" : "ld",
!(type & SLJIT_32) ? ".f64" : ".f32",
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
!(type & SLJIT_32) ? ".f64" : ".f32");
if (type & SLJIT_MEM_UNALIGNED) {
printf(".un%s%s ", (type & SLJIT_MEM_ALIGNED_16) ? ".16" : "", (type & SLJIT_MEM_ALIGNED_32) ? ".32" : "");
} else
printf((type & SLJIT_MEM_PRE) ? ".pre " : ".post ");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, mem, memw);
@ -2065,6 +2111,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co
CHECK_RETURN_OK;
}
#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */
#define SLJIT_SKIP_CHECKS(compiler)
#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
@ -2103,15 +2153,10 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
return SLJIT_SUCCESS;
#endif
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
}
#if !(defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
@ -2119,18 +2164,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_return_void(compiler);
}
#endif
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
@ -2142,31 +2181,55 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
struct sljit_jump *jump;
sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
jump = sljit_emit_jump(compiler, type ^ 0x1);
FAIL_IF(!jump);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
label = sljit_emit_label(compiler);
FAIL_IF(!label);
sljit_set_label(jump, label);
return SLJIT_SUCCESS;
}
#endif
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
&& !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
SLJIT_SKIP_CHECKS(compiler);
if (type & SLJIT_MEM_STORE)
return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0);
return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw);
}
#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM_V5 */
#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
&& !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
SLJIT_SKIP_CHECKS(compiler);
if (type & SLJIT_MEM_STORE)
return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0);
return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw);
}
#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */
/* CPU description section */
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
@ -2209,8 +2272,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
# include "sljitNativeMIPS_common.c"
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
# include "sljitNativeRISCV_common.c"
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
# include "sljitNativeSPARC_common.c"
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
# include "sljitNativeS390X.c"
#endif
@ -2286,16 +2347,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
else
flags = condition << VARIABLE_FLAG_SHIFT;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
PTR_FAIL_IF(sljit_emit_op2u(compiler,
SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));
}
@ -2326,58 +2382,47 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(reg);
SLJIT_UNUSED_ARG(mem);
SLJIT_UNUSED_ARG(memw);
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
return SLJIT_ERR_UNSUPPORTED;
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
}
#endif
#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
&& !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(type);
SLJIT_UNUSED_ARG(freg);
SLJIT_UNUSED_ARG(mem);
SLJIT_UNUSED_ARG(memw);
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
return SLJIT_ERR_UNSUPPORTED;
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
}
#endif
@ -2391,10 +2436,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
if (offset != 0)
return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);

View File

@ -446,8 +446,6 @@ struct sljit_compiler {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
sljit_s32 args_size;
sljit_s32 locals_offset;
sljit_s32 scratches_offset;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@ -493,12 +491,6 @@ struct sljit_compiler {
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
sljit_s32 delay_slot;
sljit_s32 cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/* Need to allocate register save area to make calls. */
sljit_s32 mode;
@ -702,17 +694,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type);
overwrites the previous context.
*/
/* The SLJIT_S0/SLJIT_S1 registers are not saved / restored on function
enter / return. Instead, these registers can be used to pass / return
data (such as global / local context pointers) across function calls.
This is an sljit specific (non ABI compatible) function call extension
so both the caller and called function must be compiled by sljit. */
#define SLJIT_ENTER_KEEP_S0 0x00000001
#define SLJIT_ENTER_KEEP_S0_S1 0x00000002
/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive)
are not saved / restored on function enter / return. Instead,
these registers can be used to pass / return data (such as
global / local context pointers) across function calls. The
value of n must be between 1 and 3. Furthermore, this option
is only supported by register argument calling convention, so
SLJIT_ENTER_REG_ARG (see below) must be specified as well. */
#define SLJIT_ENTER_KEEP(n) (n)
/* The compiled function uses cdecl calling
* convention instead of SLJIT_FUNC. */
#define SLJIT_ENTER_CDECL 0x00000004
/* The compiled function uses an sljit specific register argument
* calling convention. This is a lightweight function call type where
* both the caller and called function must be compiled with sljit.
* The jump type of the function call must be SLJIT_CALL_REG_ARG
* and the called function must store all arguments in registers. */
#define SLJIT_ENTER_REG_ARG 0x00000004
/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
#define SLJIT_MAX_LOCAL_SIZE 65536
@ -819,8 +815,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
Write-back is supported except for one instruction: 32 bit signed
load with [reg+imm] addressing mode on 64 bit.
mips: [reg+imm], -65536 <= imm <= 65535
sparc: [reg+imm], -4096 <= imm <= 4095
[reg+reg] is supported
Write-back is not supported
riscv: [reg+imm], -2048 <= imm <= 2047
Write-back is not supported
s390x: [reg+imm], -2^19 <= imm < 2^19
[reg+reg] is supported
Write-back is not supported
@ -1293,11 +1290,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_JUMP 34
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
#define SLJIT_FAST_CALL 35
/* Called function must be declared with the SLJIT_FUNC attribute. */
/* Default C calling convention. */
#define SLJIT_CALL 36
/* Called function must be declared with cdecl attribute.
This is the default attribute for C functions. */
#define SLJIT_CALL_CDECL 37
/* Called function must be an sljit compiled function.
See SLJIT_ENTER_REG_ARG option. */
#define SLJIT_CALL_REG_ARG 37
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
#define SLJIT_REWRITABLE_JUMP 0x1000
@ -1305,10 +1302,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
the called function returns to the caller of the current function. The
stack usage is reduced before the call, but it is not necessarily reduced
to zero. In the latter case the compiler needs to allocate space for some
arguments and the return register must be kept as well.
This feature is highly experimental and not supported on SPARC platform
at the moment. */
arguments and the return address must be stored on the stack as well. */
#define SLJIT_CALL_RETURN 0x2000
/* Emit a jump instruction. The destination is not set, only the type of the jump.
@ -1407,32 +1401,58 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */
/* Memory load operation. This is the default. */
#define SLJIT_MEM_LOAD 0x000000
/* Memory store operation. */
#define SLJIT_MEM_STORE 0x000200
/* Load or stora data from an unaligned address. */
#define SLJIT_MEM_UNALIGNED 0x000400
/* Load or store data and update the base address with a single operation. */
/* Base register is updated before the memory access. */
#define SLJIT_MEM_PRE 0x000800
/* Base register is updated after the memory access. */
#define SLJIT_MEM_POST 0x001000
/* The following flags are supported when SLJIT_MEM_UNALIGNED is specified: */
/* Defines 16 bit alignment for unaligned accesses. */
#define SLJIT_MEM_ALIGNED_16 0x010000
/* Defines 32 bit alignment for unaligned accesses. */
#define SLJIT_MEM_ALIGNED_32 0x020000
/* The following flags are supported when SLJIT_MEM_PRE or
SLJIT_MEM_POST is specified: */
/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
Instead the function returns with SLJIT_SUCCESS if the instruction
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
allows runtime checking of available instruction forms. */
#define SLJIT_MEM_SUPP 0x0200
/* Memory load operation. This is the default. */
#define SLJIT_MEM_LOAD 0x0000
/* Memory store operation. */
#define SLJIT_MEM_STORE 0x0400
/* Base register is updated before the memory access. */
#define SLJIT_MEM_PRE 0x0800
/* Base register is updated after the memory access. */
#define SLJIT_MEM_POST 0x1000
#define SLJIT_MEM_SUPP 0x010000
/* Emit a single memory load or store with update instruction. When the
requested instruction form is not supported by the CPU, it returns
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
allows specializing tight loops based on the supported instruction
forms (see SLJIT_MEM_SUPP flag).
/* The sljit_emit_mem emits instructions for various memory operations:
When SLJIT_MEM_UNALIGNED is set in type argument:
Emit instructions for unaligned memory loads or stores. When
SLJIT_UNALIGNED is not defined, the only way to access unaligned
memory data is using sljit_emit_mem. Otherwise all operations (e.g.
sljit_emit_op1/2, or sljit_emit_fop1/2) supports unaligned access.
In general, the performance of unaligned memory accesses are often
lower than aligned and should be avoided.
When SLJIT_MEM_PRE or SLJIT_MEM_POST is set in type argument:
Emit a single memory load or store with update instruction.
When the requested instruction form is not supported by the CPU,
it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the
instruction. This allows specializing tight loops based on
the supported instruction forms (see SLJIT_MEM_SUPP flag).
type must be between SLJIT_MOV and SLJIT_MOV_P and can be
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
or SLJIT_MEM_POST must be specified.
combined with SLJIT_MEM_* flags.
reg is the source or destination register, and must be
different from the base register of the mem operand
mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand
when SLJIT_MEM_PRE or SLJIT_MEM_POST is passed
mem must be a memory operand
Flags: - (does not modify flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
@ -1442,9 +1462,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
/* Same as sljit_emit_mem except the followings:
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
or SLJIT_MEM_POST must be specified.
freg is the source or destination floating point register */
combined with SLJIT_MEM_* flags.
freg is the source or destination floating point register
mem must be a memory operand
Flags: - (does not modify flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
@ -1603,7 +1625,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg);
/* The following function is a helper function for sljit_emit_op_custom.
It returns with the real machine register index of any SLJIT_FLOAT register.
Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */
Note: the index is always an even number on ARM-32, MIPS. */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg);

View File

@ -100,6 +100,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define CMP 0xe1400000
#define BKPT 0xe1200070
#define EOR 0xe0200000
#define LDR 0xe5100000
#define MOV 0xe1a00000
#define MUL 0xe0000090
#define MVN 0xe1e00000
@ -111,6 +112,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define RSC 0xe0e00000
#define SBC 0xe0c00000
#define SMULL 0xe0c00090
#define STR 0xe5000000
#define SUB 0xe0400000
#define TST 0xe1000000
#define UMULL 0xe0800090
@ -1104,8 +1106,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
local_size = ((size + local_size + 0x7) & ~0x7) - size;
compiler->local_size = local_size;
if (options & SLJIT_ENTER_REG_ARG)
arg_types = 0;
arg_types >>= SLJIT_ARG_SHIFT;
word_arg_count = 0;
saved_arg_count = 0;
#ifdef __SOFTFP__
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
@ -1148,8 +1154,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
if (offset < 4 * sizeof(sljit_sw))
FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
else
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
| RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
break;
}
@ -1310,8 +1315,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
lr_dst = SLJIT_FIRST_SAVED_REG;
}
return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
| RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
}
if (local_size > 0)
@ -1678,23 +1682,17 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
{
sljit_uw imm, offset_reg;
sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff;
SLJIT_ASSERT (arg & SLJIT_MEM);
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask));
if (!(arg & REG_MASK)) {
if (is_type1_transfer) {
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));
argw &= 0xfff;
}
else {
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));
argw &= 0xff;
}
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)(argw & ~mask)));
argw &= mask;
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,
is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
(mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw));
}
if (arg & OFFS_REG_MASK) {
@ -1702,72 +1700,53 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
arg &= REG_MASK;
argw &= 0x3;
if (argw != 0 && !is_type1_transfer) {
if (argw != 0 && (mask == 0xff)) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7)));
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
}
/* Bit 25: RM is offset. */
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7)));
RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_uw)argw << 7)));
}
arg &= REG_MASK;
if (is_type1_transfer) {
if (argw > 0xfff) {
imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
argw = argw & 0xfff;
arg = tmp_reg;
}
if (argw > mask) {
imm = get_imm((sljit_uw)(argw & ~mask));
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
argw = argw & mask;
arg = tmp_reg;
}
else if (argw < -0xfff) {
imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);
if (imm) {
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
argw = -(-argw & 0xfff);
arg = tmp_reg;
}
}
if (argw >= 0 && argw <= 0xfff)
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
if (argw < 0 && argw >= -0xfff)
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));
}
else {
if (argw > 0xff) {
imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff);
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
argw = argw & 0xff;
arg = tmp_reg;
}
else if (argw < -mask) {
imm = get_imm((sljit_uw)(-argw & ~mask));
if (imm) {
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
argw = -(-argw & mask);
arg = tmp_reg;
}
else if (argw < -0xff) {
imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
if (imm) {
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
argw = -(-argw & 0xff);
arg = tmp_reg;
}
}
if (argw <= mask && argw >= -mask) {
if (argw >= 0) {
if (mask == 0xff)
argw = TYPE2_TRANSFER_IMM(argw);
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
}
if (argw >= 0 && argw <= 0xff)
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));
argw = -argw;
if (argw < 0 && argw >= -0xff) {
argw = -argw;
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));
}
if (mask == 0xff)
argw = TYPE2_TRANSFER_IMM(argw);
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw));
}
FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25))));
}
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
@ -1965,15 +1944,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
saved_reg_list[saved_reg_count++] = 1;
if (saved_reg_count > 0) {
FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8)
FAIL_IF(push_inst(compiler, STR | 0x2d0000 | (saved_reg_count >= 3 ? 16 : 8)
| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
if (saved_reg_count >= 2) {
SLJIT_ASSERT(saved_reg_list[1] < 8);
FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
FAIL_IF(push_inst(compiler, STR | 0x8d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
}
if (saved_reg_count >= 3) {
SLJIT_ASSERT(saved_reg_list[2] < 8);
FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
FAIL_IF(push_inst(compiler, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
}
}
@ -1987,13 +1966,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
if (saved_reg_count > 0) {
if (saved_reg_count >= 3) {
SLJIT_ASSERT(saved_reg_list[2] < 8);
FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
}
if (saved_reg_count >= 2) {
SLJIT_ASSERT(saved_reg_list[1] < 8);
FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
}
return push_inst(compiler, 0xe49d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
return SLJIT_SUCCESS;
@ -2095,10 +2074,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
}
@ -2374,7 +2350,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
return SLJIT_SUCCESS;
}
#undef FPU_LOAD
#undef EMIT_FPU_DATA_TRANSFER
/* --------------------------------------------------------------------- */
@ -2482,7 +2457,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
return 0x50000000;
default:
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
return 0xe0000000;
}
}
@ -2659,7 +2634,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit
}
FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
} else
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
}
break;
}
@ -2738,51 +2713,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
#ifdef __SOFTFP__
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
return jump;
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
return jump;
}
}
}
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
#else /* !__SOFTFP__ */
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
}
#endif /* __SOFTFP__ */
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
#ifndef __SOFTFP__
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#endif /* !__SOFTFP__ */
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
#endif /* __SOFTFP__ */
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
@ -2848,47 +2820,44 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
}
#ifdef __SOFTFP__
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP;
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
if (type & SLJIT_CALL_RETURN)
return push_inst(compiler, BX | RM(TMP_REG2));
}
if (type & SLJIT_CALL_RETURN)
return push_inst(compiler, BX | RM(TMP_REG2));
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
}
#endif /* __SOFTFP__ */
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
#else /* !__SOFTFP__ */
if (type & SLJIT_CALL_RETURN) {
FAIL_IF(emit_stack_frame_release(compiler, -1));
type = SLJIT_JUMP;
}
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
#ifndef __SOFTFP__
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#endif /* !__SOFTFP__ */
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
#endif /* __SOFTFP__ */
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
@ -2969,6 +2938,231 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);
}
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
{
sljit_s32 arg = *mem;
sljit_sw argw = *memw;
sljit_uw imm;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_sw mask = max_offset >= 0x100 ? 0xfff : 0xff;
#else /* !SLJIT_CONFIG_ARM_V5 */
sljit_sw mask = 0xfff;
SLJIT_ASSERT(max_offset >= 0x100);
#endif /* SLJIT_CONFIG_ARM_V5 */
*mem = TMP_REG1;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
*memw = 0;
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 7));
}
arg &= REG_MASK;
if (arg) {
if (argw <= max_offset && argw >= -mask) {
*mem = arg;
return SLJIT_SUCCESS;
}
if (argw < 0) {
imm = get_imm((sljit_uw)(-argw & ~mask));
if (imm) {
*memw = -(-argw & mask);
return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm);
}
} else if ((argw & mask) <= max_offset) {
imm = get_imm((sljit_uw)(argw & ~mask));
if (imm) {
*memw = argw & mask;
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
}
} else {
imm = get_imm((sljit_uw)((argw | mask) + 1));
if (imm) {
*memw = (argw & mask) - (mask + 1);
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
}
}
}
imm = (sljit_uw)(argw & ~mask);
if ((argw & mask) > max_offset) {
imm += (sljit_uw)(mask + 1);
*memw = (argw & mask) - (mask + 1);
} else
*memw = argw & mask;
FAIL_IF(load_immediate(compiler, TMP_REG1, imm));
if (arg == 0)
return SLJIT_SUCCESS;
return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg));
}
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
sljit_s32 flags;
sljit_s32 steps;
sljit_uw add, shift;
switch (type & 0xff) {
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
flags = BYTE_SIZE;
if (!(type & SLJIT_MEM_STORE))
flags |= LOAD_DATA;
if ((type & 0xff) == SLJIT_MOV_S8)
flags |= SIGNED;
return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1);
case SLJIT_MOV_U16:
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 1));
flags = BYTE_SIZE;
steps = 1;
break;
case SLJIT_MOV_S16:
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 1));
flags = BYTE_SIZE | SIGNED;
steps = 1;
break;
default:
if (type & SLJIT_MEM_ALIGNED_32) {
flags = WORD_SIZE;
if (!(type & SLJIT_MEM_STORE))
flags |= LOAD_DATA;
return emit_op_mem(compiler, flags, reg, mem, memw, TMP_REG1);
}
if (!(type & SLJIT_MEM_ALIGNED_16)) {
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 3));
flags = BYTE_SIZE;
steps = 3;
break;
}
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xff - 2));
add = 1;
if (memw < 0) {
add = 0;
memw = -memw;
}
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, reg, mem, TYPE2_TRANSFER_IMM(memw))));
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (16 << 7) | (2 << 4)));
if (!add) {
memw -= 2;
if (memw <= 0) {
memw = -memw;
add = 1;
}
} else
memw += 2;
return push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw)));
}
if (reg == mem) {
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(mem)));
mem = TMP_REG1;
}
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, reg, mem, TYPE2_TRANSFER_IMM(memw))));
if (!add) {
memw -= 2;
if (memw <= 0) {
memw = -memw;
add = 1;
}
} else
memw += 2;
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(HALF_SIZE | LOAD_DATA, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))));
return push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (16 << 7));
}
SLJIT_ASSERT(steps > 0);
add = 1;
if (memw < 0) {
add = 0;
memw = -memw;
}
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, reg, mem, memw)));
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(reg) | (8 << 7) | (2 << 4)));
while (1) {
if (!add) {
memw -= 1;
if (memw == 0)
add = 1;
} else
memw += 1;
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE, add, TMP_REG2, mem, memw)));
if (--steps == 0)
return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(TMP_REG2) | (8 << 7) | (2 << 4)));
}
}
if (reg == mem) {
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(mem)));
mem = TMP_REG1;
}
shift = 8;
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, reg, mem, memw)));
do {
if (!add) {
memw -= 1;
if (memw == 0)
add = 1;
} else
memw += 1;
if (steps > 1) {
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(BYTE_SIZE | LOAD_DATA, add, TMP_REG2, mem, memw)));
FAIL_IF(push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (shift << 7)));
shift += 8;
}
} while (--steps != 0);
flags |= LOAD_DATA;
if (flags & SIGNED)
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, TYPE2_TRANSFER_IMM(memw))));
else
FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(flags, add, TMP_REG2, mem, memw)));
return push_inst(compiler, ORR | RD(reg) | RN(reg) | RM(TMP_REG2) | (shift << 7));
}
#endif /* SLJIT_CONFIG_ARM_V5 */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
@ -2979,6 +3173,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
is_type1_transfer = 1;
switch (type & 0xff) {
@ -3074,6 +3271,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_s32 max_offset;
sljit_s32 dst;
#endif /* SLJIT_CONFIG_ARM_V5 */
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_MEM_ALIGNED_32)
return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
if (type & SLJIT_32)
return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw);
max_offset = 0xfff - 7;
if (type & SLJIT_MEM_ALIGNED_16)
max_offset++;
FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset));
mem |= SLJIT_MEM;
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw));
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
return sljit_emit_mem_unaligned(compiler, SLJIT_MOV | SLJIT_MEM_STORE | (type & SLJIT_MEM_ALIGNED_16), TMP_REG2, mem, memw + 4);
}
max_offset = (type & SLJIT_32) ? 0xfff - 3 : 0xfff - 7;
if (type & SLJIT_MEM_ALIGNED_16)
max_offset++;
FAIL_IF(update_mem_addr(compiler, &mem, &memw, max_offset));
dst = TMP_REG1;
/* Stack offset adjustment is not needed because dst
is not stored on the stack when mem is SLJIT_SP. */
if (mem == TMP_REG1) {
dst = SLJIT_R3;
if (compiler->scratches >= 4)
FAIL_IF(push_inst(compiler, STR | (1 << 21) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8));
}
mem |= SLJIT_MEM;
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw));
FAIL_IF(push_inst(compiler, VMOV | VN(freg) | RD(dst)));
if (!(type & SLJIT_32)) {
FAIL_IF(sljit_emit_mem_unaligned(compiler, SLJIT_MOV | (type & SLJIT_MEM_ALIGNED_16), dst, mem, memw + 4));
FAIL_IF(push_inst(compiler, VMOV | VN(freg) | 0x80 | RD(dst)));
}
if (dst == SLJIT_R3 && compiler->scratches >= 4)
FAIL_IF(push_inst(compiler, (LDR ^ (0x1 << 24)) | (0x1 << 23) | RN(SLJIT_SP) | RD(SLJIT_R3) | 8));
return SLJIT_SUCCESS;
#else /* !SLJIT_CONFIG_ARM_V5 */
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
if (type & SLJIT_32)
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1);
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
mem |= SLJIT_MEM;
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1);
}
if (type & SLJIT_32) {
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2));
}
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
mem |= SLJIT_MEM;
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1));
return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1));
#endif /* SLJIT_CONFIG_ARM_V5 */
}
#undef FPU_LOAD
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;

View File

@ -1001,23 +1001,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
if (prev != -1)
FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
arg_types >>= SLJIT_ARG_SHIFT;
#ifdef _WIN32
if (local_size > 4096)
FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
#endif /* _WIN32 */
tmp = SLJIT_R0;
while (arg_types > 0) {
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp)));
saved_arg_count++;
}
tmp++;
}
if (!(options & SLJIT_ENTER_REG_ARG)) {
arg_types >>= SLJIT_ARG_SHIFT;
saved_arg_count = 0;
tmp = SLJIT_R0;
while (arg_types) {
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - saved_arg_count) | RN(TMP_ZERO) | RM(tmp)));
saved_arg_count++;
}
tmp++;
}
arg_types >>= SLJIT_ARG_SHIFT;
}
}
#ifdef _WIN32
@ -1390,10 +1394,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
}
@ -1833,11 +1834,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
@ -1927,11 +1924,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
type = SLJIT_JUMP;
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
@ -2016,6 +2009,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
return SLJIT_ERR_UNSUPPORTED;
@ -2070,6 +2066,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
return SLJIT_ERR_UNSUPPORTED;

View File

@ -890,8 +890,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
#define HALF_SIZE 0x08
#define PRELOAD 0x0c
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))
#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))
/*
1st letter:
@ -993,8 +993,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
sljit_uw tmp;
SLJIT_ASSERT(arg & SLJIT_MEM);
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
arg &= ~SLJIT_MEM;
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -0xff && argw <= 0xfff));
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
@ -1012,15 +1011,17 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
other_r = OFFS_REG(arg);
arg &= 0xf;
arg &= REG_MASK;
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4));
}
arg &= REG_MASK;
if (argw > 0xfff) {
tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
tmp = get_imm((sljit_uw)(argw & ~0xfff));
if (tmp != INVALID_IMM) {
push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
arg = tmp_reg;
@ -1028,7 +1029,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
else if (argw < -0xff) {
tmp = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
tmp = get_imm((sljit_uw)(-argw & ~0xff));
if (tmp != INVALID_IMM) {
push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
arg = tmp_reg;
@ -1036,27 +1037,28 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
/* 16 bit instruction forms. */
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
tmp = 3;
if (IS_WORD_SIZE(flags)) {
if (OFFSET_CHECK(0x1f, 2))
if (ALIGN_CHECK(argw, 0x1f, 2))
tmp = 2;
}
else if (flags & BYTE_SIZE)
{
if (OFFSET_CHECK(0x1f, 0))
if (ALIGN_CHECK(argw, 0x1f, 0))
tmp = 0;
}
else {
SLJIT_ASSERT(flags & HALF_SIZE);
if (OFFSET_CHECK(0x1f, 1))
if (ALIGN_CHECK(argw, 0x1f, 1))
tmp = 1;
}
if (tmp < 3)
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));
}
else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {
else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && ALIGN_CHECK(argw, 0xff, 2) && reg_map[reg] <= 7) {
/* SP based immediate. */
return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));
}
@ -1074,6 +1076,9 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
}
#undef ALIGN_CHECK
#undef IS_WORD_SIZE
/* --------------------------------------------------------------------- */
/* Entry, exit */
/* --------------------------------------------------------------------- */
@ -1132,8 +1137,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
local_size = ((size + local_size + 0x7) & ~0x7) - size;
compiler->local_size = local_size;
if (options & SLJIT_ENTER_REG_ARG)
arg_types = 0;
arg_types >>= SLJIT_ARG_SHIFT;
word_arg_count = 0;
saved_arg_count = 0;
#ifdef __SOFTFP__
SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
@ -1690,10 +1699,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
}
@ -1960,8 +1966,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
}
#undef FPU_LOAD
/* --------------------------------------------------------------------- */
/* Other instructions */
/* --------------------------------------------------------------------- */
@ -2310,52 +2314,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
#ifdef __SOFTFP__
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
return jump;
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
return jump;
}
}
}
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
#else
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
}
#endif /* __SOFTFP__ */
if (type & SLJIT_CALL_RETURN) {
/* ldmia sp!, {..., lr} */
PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
#ifndef __SOFTFP__
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#endif /* !__SOFTFP__ */
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
#endif
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
@ -2412,48 +2413,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
}
#ifdef __SOFTFP__
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
SLJIT_ASSERT((extra_space & 0x7) == 0);
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP;
if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
type = SLJIT_JUMP;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
if (extra_space > 0) {
if (type & SLJIT_CALL_RETURN)
FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
| RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
if (type & SLJIT_CALL_RETURN)
return push_inst16(compiler, BX | RN3(TMP_REG2));
}
if (type & SLJIT_CALL_RETURN)
return push_inst16(compiler, BX | RN3(TMP_REG2));
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
}
#endif /* __SOFTFP__ */
SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
#else /* !__SOFTFP__ */
if (type & SLJIT_CALL_RETURN) {
/* ldmia sp!, {..., lr} */
FAIL_IF(emit_stack_frame_release(compiler, -1));
type = SLJIT_JUMP;
}
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
#ifndef __SOFTFP__
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#endif /* !__SOFTFP__ */
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
#endif /* __SOFTFP__ */
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
@ -2567,6 +2565,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))
return SLJIT_ERR_UNSUPPORTED;
@ -2615,6 +2616,109 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);
}
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
{
sljit_s32 arg = *mem;
sljit_sw argw = *memw;
sljit_uw imm;
*mem = TMP_REG1;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
*memw = 0;
return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 6));
}
arg &= REG_MASK;
if (arg) {
if (argw <= max_offset && argw >= -0xff) {
*mem = arg;
return SLJIT_SUCCESS;
}
if (argw < 0) {
imm = get_imm((sljit_uw)(-argw & ~0xff));
if (imm) {
*memw = -(-argw & 0xff);
return push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg) | imm);
}
} else if ((argw & 0xfff) <= max_offset) {
imm = get_imm((sljit_uw)(argw & ~0xfff));
if (imm) {
*memw = argw & 0xfff;
return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
}
} else {
imm = get_imm((sljit_uw)((argw | 0xfff) + 1));
if (imm) {
*memw = (argw & 0xfff) - 0x1000;
return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
}
}
}
imm = (sljit_uw)(argw & ~0xfff);
if ((argw & 0xfff) > max_offset) {
imm += 0x1000;
*memw = (argw & 0xfff) - 0x1000;
} else
*memw = argw & 0xfff;
FAIL_IF(load_immediate(compiler, TMP_REG1, imm));
if (arg == 0)
return SLJIT_SUCCESS;
return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, arg));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_MEM_ALIGNED_32)
return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | RT4(TMP_REG2)));
if (type & SLJIT_32)
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1);
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
mem |= SLJIT_MEM;
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1));
FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | DN4(freg) | 0x80 | RT4(TMP_REG2)));
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1);
}
if (type & SLJIT_32) {
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
return push_inst32(compiler, VMOV | DN4(freg) | RT4(TMP_REG2));
}
FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
mem |= SLJIT_MEM;
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1));
return push_inst32(compiler, VMOV2 | DM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1));
}
#undef FPU_LOAD
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;

View File

@ -196,8 +196,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
sljit_s32 arg_types)
{
struct sljit_jump *jump;
sljit_u32 extra_space = (sljit_u32)type;
sljit_ins ins;
sljit_u32 extra_space = 0;
sljit_ins ins = NOP;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
@ -206,12 +206,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
extra_space = (sljit_u32)type;
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
} else if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
jump->flags |= IS_JAL | IS_CALL;
jump->flags |= IS_JAL;
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
jump->flags |= IS_CALL;
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
} else
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
@ -247,16 +258,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
src = PIC_ADDR_REG;
srcw = 0;
}
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
if (type & SLJIT_CALL_RETURN) {
if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
src = PIC_ADDR_REG;
srcw = 0;
}
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
if (ins != NOP)
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
}
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src & SLJIT_IMM)
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
else if (FAST_IS_REG(src))
else if (src != PIC_ADDR_REG)
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
else if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
}
FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));

View File

@ -238,12 +238,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
if (!(type & SLJIT_CALL_RETURN)) {
jump->flags |= IS_JAL | IS_CALL;
jump->flags |= IS_JAL;
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
jump->flags |= IS_CALL;
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
} else
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
@ -265,16 +273,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
src = PIC_ADDR_REG;
srcw = 0;
}
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
if (type & SLJIT_CALL_RETURN) {
if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
src = PIC_ADDR_REG;
srcw = 0;
}
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
if (ins != NOP)
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
}
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src & SLJIT_IMM)
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
else if (FAST_IS_REG(src))
else if (src != PIC_ADDR_REG)
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
else if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
}
if (type & SLJIT_CALL_RETURN)
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));

View File

@ -212,9 +212,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define JR (HI(0) | LO(8))
#endif /* SLJIT_MIPS_REV >= 6 */
#define LD (HI(55))
#define LDL (HI(26))
#define LDR (HI(27))
#define LDC1 (HI(53))
#define LUI (HI(15))
#define LW (HI(35))
#define LWL (HI(34))
#define LWR (HI(38))
#define LWC1 (HI(49))
#define MFC1 (HI(17))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
@ -242,6 +246,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define OR (HI(0) | LO(37))
#define ORI (HI(13))
#define SD (HI(63))
#define SDL (HI(44))
#define SDR (HI(45))
#define SDC1 (HI(61))
#define SLT (HI(0) | LO(42))
#define SLTI (HI(10))
@ -256,6 +262,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define SUB_S (HI(17) | FMT_S | LO(1))
#define SUBU (HI(0) | LO(35))
#define SW (HI(43))
#define SWL (HI(42))
#define SWR (HI(46))
#define SWC1 (HI(57))
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
#define XOR (HI(0) | LO(38))
@ -283,11 +291,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define ADDU_W ADDU
#define ADDIU_W ADDIU
#define SLL_W SLL
#define SRA_W SRA
#define SUBU_W SUBU
#else
#define ADDU_W DADDU
#define ADDIU_W DADDIU
#define SLL_W DSLL
#define SRA_W DSRA
#define SUBU_W DSUBU
#endif
@ -371,15 +381,14 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
jump->addr -= 2 * sizeof(sljit_ins);
return inst;
}
}
else {
} else {
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
jump->flags |= PATCH_B;
if (!(jump->flags & IS_COND)) {
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
inst[1] = NOP;
/* Keep inst[1] */
return inst + 1;
}
inst[0] ^= invert_branch(jump->flags);
@ -422,7 +431,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
inst[1] = NOP;
/* Keep inst[1] */
return inst + 1;
}
}
@ -802,27 +811,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
#endif
compiler->local_size = local_size;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
tmp = arg_types >> SLJIT_ARG_SHIFT;
arg_count = 0;
offset = 0;
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
if (!(options & SLJIT_ENTER_REG_ARG)) {
tmp = arg_types >> SLJIT_ARG_SHIFT;
arg_count = 0;
while (tmp) {
offset = arg_count;
if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
if ((arg_count & 0x1) != 0)
while (tmp) {
offset = arg_count;
if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
if ((arg_count & 0x1) != 0)
arg_count++;
arg_count++;
}
arg_count++;
tmp >>= SLJIT_ARG_SHIFT;
}
arg_count++;
tmp >>= SLJIT_ARG_SHIFT;
compiler->args_size = (sljit_uw)arg_count << 2;
offset = (offset >= 4) ? (offset << 2) : 0;
}
compiler->args_size = (sljit_uw)arg_count << 2;
offset = (offset >= 4) ? (offset << 2) : 0;
#else /* !SLJIT_CONFIG_MIPS_32 */
offset = 0;
#endif /* SLJIT_CONFIG_MIPS_32 */
if (local_size + offset <= -SIMM_MIN) {
@ -831,9 +840,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
base = S(SLJIT_SP);
offset = local_size - SSIZE_OF(sw);
} else {
FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
base = S(TMP_REG2);
offset = -SSIZE_OF(sw);
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
@ -871,6 +880,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
}
if (options & SLJIT_ENTER_REG_ARG)
return SLJIT_SUCCESS;
arg_types >>= SLJIT_ARG_SHIFT;
arg_count = 0;
word_arg_count = 0;
@ -1305,8 +1317,6 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
}
#undef TO_ARGW_HI
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
{
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
@ -2170,10 +2180,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
}
@ -2254,8 +2261,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
if (FAST_IS_REG(dst))
return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
if (FAST_IS_REG(dst)) {
FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
return SLJIT_SUCCESS;
}
/* Store the integer value from a VFP register. */
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
@ -2277,9 +2289,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (FAST_IS_REG(src))
if (FAST_IS_REG(src)) {
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
else if (src & SLJIT_MEM) {
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
} else if (src & SLJIT_MEM) {
/* Load the integer value into a VFP register. */
FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
}
@ -2290,6 +2305,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
#endif
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
}
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
@ -3050,6 +3068,265 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
#endif /* SLJIT_MIPS_REV >= 1 */
}
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
{
sljit_s32 arg = *mem;
sljit_sw argw = *memw;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
if (SLJIT_UNLIKELY(argw)) {
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
} else
FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
*mem = TMP_REG1;
*memw = 0;
return SLJIT_SUCCESS;
}
if (argw <= max_offset && argw >= SIMM_MIN) {
*mem = arg & REG_MASK;
return SLJIT_SUCCESS;
}
*mem = TMP_REG1;
if ((sljit_s16)argw > max_offset) {
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
*memw = 0;
} else {
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
*memw = (sljit_s16)argw;
}
if ((arg & REG_MASK) == 0)
return SLJIT_SUCCESS;
return push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1));
}
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
#define MEM16_IMM_FIRST(memw) IMM((memw) + 1)
#define MEM16_IMM_SECOND(memw) IMM(memw)
#define MEMF64_FS_FIRST(freg) FS(freg)
#define MEMF64_FS_SECOND(freg) (FS(freg) | ((sljit_ins)1 << 11))
#else /* !SLJIT_LITTLE_ENDIAN */
#define MEM16_IMM_FIRST(memw) IMM(memw)
#define MEM16_IMM_SECOND(memw) IMM((memw) + 1)
#define MEMF64_FS_FIRST(freg) (FS(freg) | ((sljit_ins)1 << 11))
#define MEMF64_FS_SECOND(freg) FS(freg)
#endif /* SLJIT_LITTLE_ENDIAN */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 reg,
sljit_s32 mem, sljit_sw memw)
{
sljit_s32 op = type & 0xff;
sljit_s32 flags = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
switch (op) {
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
flags = BYTE_DATA;
if (!(type & SLJIT_MEM_STORE))
flags |= LOAD_DATA;
if (op == SLJIT_MOV_S8)
flags |= SIGNED_DATA;
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), MOVABLE_INS));
return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), MOVABLE_INS);
}
flags = BYTE_DATA | LOAD_DATA;
if (op == SLJIT_MOV_S16)
flags |= SIGNED_DATA;
FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | MEM16_IMM_FIRST(memw), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | MEM16_IMM_SECOND(memw), DR(reg)));
FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
case SLJIT_MOV:
case SLJIT_MOV_P:
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
if (type & SLJIT_MEM_ALIGNED_32) {
flags = WORD_DATA;
if (!(type & SLJIT_MEM_STORE))
flags |= LOAD_DATA;
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
}
#else /* !SLJIT_CONFIG_MIPS_32 */
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
return push_inst(compiler, SDR | S(mem) | T(reg) | IMM(memw + 7), MOVABLE_INS);
}
if (mem == reg) {
FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
mem = TMP_REG1;
}
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM(memw), DR(reg)));
return push_inst(compiler, LDR | S(mem) | T(reg) | IMM(memw + 7), DR(reg));
#endif /* SLJIT_CONFIG_MIPS_32 */
}
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
if (type & SLJIT_MEM_STORE) {
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM(memw), MOVABLE_INS));
return push_inst(compiler, SWR | S(mem) | T(reg) | IMM(memw + 3), MOVABLE_INS);
}
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
if (mem == reg) {
FAIL_IF(push_inst(compiler, ADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
mem = TMP_REG1;
}
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
return push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg));
#else /* !SLJIT_CONFIG_MIPS_32 */
if (mem == reg) {
FAIL_IF(push_inst(compiler, DADDU | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
mem = TMP_REG1;
}
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM(memw), DR(reg)));
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM(memw + 3), DR(reg)));
if (op == SLJIT_MOV_U32) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11) | (0 << 11), DR(reg));
#else /* SLJIT_MIPS_REV < 1 */
FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
#endif /* SLJIT_MIPS_REV >= 2 */
}
return SLJIT_SUCCESS;
#endif /* SLJIT_CONFIG_MIPS_32 */
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 freg,
sljit_s32 mem, sljit_sw memw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if (type & (SLJIT_MEM_PRE | SLJIT_MEM_POST))
return SLJIT_ERR_UNSUPPORTED;
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
if (type & SLJIT_MEM_STORE) {
if (type & SLJIT_32) {
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS);
}
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), DR(TMP_REG2)));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), MOVABLE_INS));
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), DR(TMP_REG2)));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), MOVABLE_INS));
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
#else /* !SLJIT_CONFIG_MIPS_32 */
FAIL_IF(push_inst(compiler, MFC1 | (1 << 21) | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM(memw), MOVABLE_INS));
return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), MOVABLE_INS);
#endif /* SLJIT_CONFIG_MIPS_32 */
}
if (type & SLJIT_32) {
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
return SLJIT_SUCCESS;
}
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 3), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_FIRST(freg), MOVABLE_INS));
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM(memw + 4), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | MEMF64_FS_SECOND(freg), MOVABLE_INS));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
#else /* !SLJIT_CONFIG_MIPS_32 */
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM(memw), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM(memw + 7), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, MTC1 | (1 << 21) | T(TMP_REG2) | FS(freg), MOVABLE_INS));
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 3)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif
#endif /* SLJIT_CONFIG_MIPS_32 */
return SLJIT_SUCCESS;
}
#undef MEM16_IMM_FIRST
#undef MEM16_IMM_SECOND
#undef MEMF64_FS_FIRST
#undef MEMF64_FS_SECOND
#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
#undef TO_ARGW_HI
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
{
struct sljit_const *const_;

View File

@ -735,8 +735,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1)
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
if (!(options & SLJIT_ENTER_REG_ARG))
local_size += SSIZE_OF(sw);
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
compiler->local_size = local_size;
@ -775,8 +779,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
}
offset -= SSIZE_OF(sw);
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
if (!(options & SLJIT_ENTER_REG_ARG)) {
offset -= SSIZE_OF(sw);
FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
}
tmp = SLJIT_S0 - saveds;
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
@ -790,9 +796,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
}
FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
if (options & SLJIT_ENTER_REG_ARG)
return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
arg_types >>= SLJIT_ARG_SHIFT;
saved_arg_count = 0;
while (arg_types > 0) {
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
@ -834,13 +845,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1)
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
+ GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
if (!(options & SLJIT_ENTER_REG_ARG))
local_size += SSIZE_OF(sw);
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
return SLJIT_SUCCESS;
}
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
{
sljit_s32 i, tmp, base, offset;
@ -872,8 +886,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
}
offset -= SSIZE_OF(sw);
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
offset -= SSIZE_OF(sw);
FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
}
tmp = SLJIT_S0 - compiler->saveds;
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
@ -1631,7 +1647,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
if (GET_OPCODE(op) != SLJIT_AND) {
if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
/* Unlike or and xor, the and resets unwanted bits as well. */
if (TEST_UI_IMM(src2, src2w)) {
compiler->imm = (sljit_ins)src2w;
@ -1668,10 +1684,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
}
@ -2139,7 +2152,7 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type
return (4 << 21) | ((4 + 3) << 16);
default:
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
return (20 << 21);
}
}
@ -2186,7 +2199,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
#endif
if (type & SLJIT_CALL_RETURN) {
@ -2194,11 +2208,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
@ -2272,14 +2282,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
}
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
FAIL_IF(call_with_args(compiler, arg_types, &src));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
FAIL_IF(call_with_args(compiler, arg_types, &src));
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
@ -2429,10 +2436,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
if (dst & SLJIT_MEM)
return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
@ -2458,6 +2463,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
if (type & SLJIT_MEM_POST)
return SLJIT_ERR_UNSUPPORTED;
@ -2554,6 +2562,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if (type & SLJIT_MEM_UNALIGNED)
return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
if (type & SLJIT_MEM_POST)
return SLJIT_ERR_UNSUPPORTED;

View File

@ -665,7 +665,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
else if (local_size > 0)
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
if (options & SLJIT_ENTER_REG_ARG)
return SLJIT_SUCCESS;
arg_types >>= SLJIT_ARG_SHIFT;
saved_arg_count = 0;
tmp = SLJIT_R0;
while (arg_types > 0) {
@ -1727,10 +1731,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
}
@ -2199,11 +2200,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
@ -2368,11 +2365,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
type = SLJIT_JUMP;
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}

View File

@ -1729,7 +1729,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
if (options & SLJIT_ENTER_REG_ARG)
return SLJIT_SUCCESS;
arg_types >>= SLJIT_ARG_SHIFT;
saved_arg_count = 0;
tmp = 0;
while (arg_types > 0) {
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
@ -2800,10 +2804,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w);
}
@ -3192,11 +3193,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
@ -3248,11 +3245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
type = SLJIT_JUMP;
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}

View File

@ -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

View File

@ -101,34 +101,38 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if (!(b & OFFS_REG_MASK)) {
if (NOT_HALFWORD(immb)) {
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
immb = 0;
if (b & REG_MASK)
b |= TO_OFFS_REG(TMP_REG2);
else
b |= TMP_REG2;
}
else if (reg_lmap[b & REG_MASK] == 4)
b |= TO_OFFS_REG(SLJIT_SP);
if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
immb = 0;
if (b & REG_MASK)
b |= TO_OFFS_REG(TMP_REG2);
else
b |= TMP_REG2;
}
if (!(b & REG_MASK))
inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
else {
if (reg_map[b & REG_MASK] >= 8)
rex |= REX_B;
if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
if (immb != 0 && !(b & OFFS_REG_MASK)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
inst_size += sizeof(sljit_s8);
else
inst_size += sizeof(sljit_s32);
}
else if (reg_lmap[b & REG_MASK] == 5)
inst_size += sizeof(sljit_s8);
else if (reg_lmap[b & REG_MASK] == 5) {
/* Swap registers if possible. */
if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5)
b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
else
inst_size += sizeof(sljit_s8);
}
if (reg_map[b & REG_MASK] >= 8)
rex |= REX_B;
if (reg_lmap[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))
b |= TO_OFFS_REG(SLJIT_SP);
if (b & OFFS_REG_MASK) {
inst_size += 1; /* SIB byte. */
@ -223,7 +227,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
} else if (b & REG_MASK) {
reg_lmap_b = reg_lmap[b & REG_MASK];
if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_lmap_b == 5) {
if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
if (immb != 0 || reg_lmap_b == 5) {
if (immb <= 127 && immb >= -128)
*buf_ptr |= 0x40;
@ -248,8 +252,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
}
}
else {
if (reg_lmap_b == 5)
*buf_ptr |= 0x40;
*buf_ptr++ |= 0x04;
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
if (reg_lmap_b == 5)
*buf_ptr++ = 0;
}
}
else {
@ -379,6 +389,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
if (options & SLJIT_ENTER_REG_ARG)
arg_types = 0;
/* Emit ENDBR64 at function entry if needed. */
FAIL_IF(emit_endbranch(compiler));
@ -786,17 +799,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
compiler->mode32 = 0;
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
if (type & SLJIT_CALL_RETURN) {
PTR_FAIL_IF(emit_stack_frame_release(compiler));
type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_jump(compiler, type);
}
@ -822,16 +833,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
}
FAIL_IF(emit_stack_frame_release(compiler));
type = SLJIT_JUMP;
}
FAIL_IF(call_with_args(compiler, arg_types, &src));
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
FAIL_IF(call_with_args(compiler, arg_types, &src));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
if (type & SLJIT_CALL_RETURN)
type = SLJIT_JUMP;
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}

View File

@ -26,11 +26,7 @@
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
{
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
return "x86" SLJIT_CPUINFO " ABI:fastcall";
#else
return "x86" SLJIT_CPUINFO;
#endif
}
/*
@ -79,9 +75,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
#define CHECK_EXTRA_REGS(p, w, do) \
if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
if (p <= compiler->scratches) \
w = compiler->scratches_offset + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
else \
w = compiler->locals_offset + ((p) - SLJIT_S2) * SSIZE_OF(sw); \
w = SLJIT_LOCALS_OFFSET_BASE + ((p) - SLJIT_S2) * SSIZE_OF(sw); \
p = SLJIT_MEM1(SLJIT_SP); \
do; \
}
@ -2338,10 +2334,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compil
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
}
@ -2851,10 +2844,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
}
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
#else
@ -2965,10 +2955,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
if (GET_OPCODE(op) < SLJIT_ADD)
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
#endif /* SLJIT_CONFIG_X86_64 */
}

File diff suppressed because it is too large Load Diff

6069
waterbox/ares64/ares/thirdparty/xxhash.h vendored Normal file

File diff suppressed because it is too large Load Diff