| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709 |
- /* Bra.c -- Branch converters for RISC code
- 2024-01-20 : Igor Pavlov : Public domain */
- #include "Precomp.h"
- #include "Bra.h"
- #include "RotateDefs.h"
- #include "CpuArch.h"
- #if defined(MY_CPU_SIZEOF_POINTER) \
- && ( MY_CPU_SIZEOF_POINTER == 4 \
- || MY_CPU_SIZEOF_POINTER == 8)
- #define BR_CONV_USE_OPT_PC_PTR
- #endif
- #ifdef BR_CONV_USE_OPT_PC_PTR
- #define BR_PC_INIT pc -= (UInt32)(SizeT)p;
- #define BR_PC_GET (pc + (UInt32)(SizeT)p)
- #else
- #define BR_PC_INIT pc += (UInt32)size;
- #define BR_PC_GET (pc - (UInt32)(SizeT)(lim - p))
- // #define BR_PC_INIT
- // #define BR_PC_GET (pc + (UInt32)(SizeT)(p - data))
- #endif
- #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
- // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
- #define Z7_BRANCH_CONV(name) z7_ ## name
- #define Z7_BRANCH_FUNC_MAIN(name) \
- static \
- Z7_FORCE_INLINE \
- Z7_ATTRIB_NO_VECTOR \
- Byte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding)
- #define Z7_BRANCH_FUNC_IMP(name, m, encoding) \
- Z7_NO_INLINE \
- Z7_ATTRIB_NO_VECTOR \
- Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
- { return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \
- #ifdef Z7_EXTRACT_ONLY
- #define Z7_BRANCH_FUNCS_IMP(name) \
- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)
- #else
- #define Z7_BRANCH_FUNCS_IMP(name) \
- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \
- Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)
- #endif
- #if defined(__clang__)
- #define BR_EXTERNAL_FOR
- #define BR_NEXT_ITERATION continue;
- #else
- #define BR_EXTERNAL_FOR for (;;)
- #define BR_NEXT_ITERATION break;
- #endif
- #if defined(__clang__) && (__clang_major__ >= 8) \
- || defined(__GNUC__) && (__GNUC__ >= 1000) \
- // GCC is not good for __builtin_expect() here
- /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */
- // #define Z7_unlikely [[unlikely]]
- // #define Z7_LIKELY(x) (__builtin_expect((x), 1))
- #define Z7_UNLIKELY(x) (__builtin_expect((x), 0))
- // #define Z7_likely [[likely]]
- #else
- // #define Z7_LIKELY(x) (x)
- #define Z7_UNLIKELY(x) (x)
- // #define Z7_likely
- #endif
- Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)
- {
- // Byte *p = data;
- const Byte *lim;
- const UInt32 flag = (UInt32)1 << (24 - 4);
- const UInt32 mask = ((UInt32)1 << 24) - (flag << 1);
- size &= ~(SizeT)3;
- // if (size == 0) return p;
- lim = p + size;
- BR_PC_INIT
- pc -= 4; // because (p) will point to next instruction
-
- BR_EXTERNAL_FOR
- {
- // Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
- for (;;)
- {
- UInt32 v;
- if Z7_UNLIKELY(p == lim)
- return p;
- v = GetUi32a(p);
- p += 4;
- if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0)
- {
- UInt32 c = BR_PC_GET >> 2;
- BR_CONVERT_VAL(v, c)
- v &= 0x03ffffff;
- v |= 0x94000000;
- SetUi32a(p - 4, v)
- BR_NEXT_ITERATION
- }
- // v = rotlFixed(v, 8); v += (flag << 8) - 0x90; if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0)
- v -= 0x90000000; if Z7_UNLIKELY((v & 0x9f000000) == 0)
- {
- UInt32 z, c;
- // v = rotrFixed(v, 8);
- v += flag; if Z7_UNLIKELY(v & mask) continue;
- z = (v & 0xffffffe0) | (v >> 26);
- c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7;
- BR_CONVERT_VAL(z, c)
- v &= 0x1f;
- v |= 0x90000000;
- v |= z << 26;
- v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag);
- SetUi32a(p - 4, v)
- }
- }
- }
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64)
- Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)
- {
- // Byte *p = data;
- const Byte *lim;
- size &= ~(SizeT)3;
- lim = p + size;
- BR_PC_INIT
- /* in ARM: branch offset is relative to the +2 instructions from current instruction.
- (p) will point to next instruction */
- pc += 8 - 4;
-
- for (;;)
- {
- for (;;)
- {
- if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
- if Z7_UNLIKELY(p >= lim) { return p; } p += 4; if Z7_UNLIKELY(p[-1] == 0xeb) break;
- }
- {
- UInt32 v = GetUi32a(p - 4);
- UInt32 c = BR_PC_GET >> 2;
- BR_CONVERT_VAL(v, c)
- v &= 0x00ffffff;
- v |= 0xeb000000;
- SetUi32a(p - 4, v)
- }
- }
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_ARM)
- Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)
- {
- // Byte *p = data;
- const Byte *lim;
- size &= ~(SizeT)3;
- lim = p + size;
- BR_PC_INIT
- pc -= 4; // because (p) will point to next instruction
-
- for (;;)
- {
- UInt32 v;
- for (;;)
- {
- if Z7_UNLIKELY(p == lim)
- return p;
- // v = GetBe32a(p);
- v = *(UInt32 *)(void *)p;
- p += 4;
- // if ((v & 0xfc000003) == 0x48000001) break;
- // if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break;
- if Z7_UNLIKELY(
- ((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001))
- & Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break;
- }
- {
- v = Z7_CONV_NATIVE_TO_BE_32(v);
- {
- UInt32 c = BR_PC_GET;
- BR_CONVERT_VAL(v, c)
- }
- v &= 0x03ffffff;
- v |= 0x48000000;
- SetBe32a(p - 4, v)
- }
- }
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_PPC)
- #ifdef Z7_CPU_FAST_ROTATE_SUPPORTED
- #define BR_SPARC_USE_ROTATE
- #endif
- Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)
- {
- // Byte *p = data;
- const Byte *lim;
- const UInt32 flag = (UInt32)1 << 22;
- size &= ~(SizeT)3;
- lim = p + size;
- BR_PC_INIT
- pc -= 4; // because (p) will point to next instruction
- for (;;)
- {
- UInt32 v;
- for (;;)
- {
- if Z7_UNLIKELY(p == lim)
- return p;
- /* // the code without GetBe32a():
- { const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; }
- */
- v = GetBe32a(p);
- p += 4;
- #ifdef BR_SPARC_USE_ROTATE
- v = rotlFixed(v, 2);
- v += (flag << 2) - 1;
- if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0)
- #else
- v += (UInt32)5 << 29;
- v ^= (UInt32)7 << 29;
- v += flag;
- if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0)
- #endif
- break;
- }
- {
- // UInt32 v = GetBe32a(p - 4);
- #ifndef BR_SPARC_USE_ROTATE
- v <<= 2;
- #endif
- {
- UInt32 c = BR_PC_GET;
- BR_CONVERT_VAL(v, c)
- }
- v &= (flag << 3) - 1;
- #ifdef BR_SPARC_USE_ROTATE
- v -= (flag << 2) - 1;
- v = rotrFixed(v, 2);
- #else
- v -= (flag << 2);
- v >>= 2;
- v |= (UInt32)1 << 30;
- #endif
- SetBe32a(p - 4, v)
- }
- }
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC)
- Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)
- {
- // Byte *p = data;
- Byte *lim;
- size &= ~(SizeT)1;
- // if (size == 0) return p;
- if (size <= 2) return p;
- size -= 2;
- lim = p + size;
- BR_PC_INIT
- /* in ARM: branch offset is relative to the +2 instructions from current instruction.
- (p) will point to the +2 instructions from current instruction */
- // pc += 4 - 4;
- // if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1;
- // #define ARMT_TAIL_PROC { goto armt_tail; }
- #define ARMT_TAIL_PROC { return p; }
-
- do
- {
- /* in MSVC 32-bit x86 compilers:
- UInt32 version : it loads value from memory with movzx
- Byte version : it loads value to 8-bit register (AL/CL)
- movzx version is slightly faster in some cpus
- */
- unsigned b1;
- // Byte / unsigned
- b1 = p[1];
- // optimized version to reduce one (p >= lim) check:
- // unsigned a1 = p[1]; b1 = p[3]; p += 2; if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8)
- for (;;)
- {
- unsigned b3; // Byte / UInt32
- /* (Byte)(b3) normalization can use low byte computations in MSVC.
- It gives smaller code, and no loss of speed in some compilers/cpus.
- But new MSVC 32-bit x86 compilers use more slow load
- from memory to low byte register in that case.
- So we try to use full 32-bit computations for faster code.
- */
- // if (p >= lim) { ARMT_TAIL_PROC } b3 = b1 + 8; b1 = p[3]; p += 2; if ((b3 & b1) >= 0xf8) break;
- if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b3 = p[3]; p += 2; if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break;
- if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC } b1 = p[3]; p += 2; if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break;
- }
- {
- /* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation.
- But gcc/clang for arm64 can use bfi instruction for full code here */
- UInt32 v =
- ((UInt32)GetUi16a(p - 2) << 11) |
- ((UInt32)GetUi16a(p) & 0x7FF);
- /*
- UInt32 v =
- ((UInt32)p[1 - 2] << 19)
- + (((UInt32)p[1] & 0x7) << 8)
- + (((UInt32)p[-2] << 11))
- + (p[0]);
- */
- p += 2;
- {
- UInt32 c = BR_PC_GET >> 1;
- BR_CONVERT_VAL(v, c)
- }
- SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000))
- SetUi16a(p - 2, (UInt16)(v | 0xf800))
- /*
- p[-4] = (Byte)(v >> 11);
- p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7));
- p[-2] = (Byte)v;
- p[-1] = (Byte)(0xf8 | (v >> 8));
- */
- }
- }
- while (p < lim);
- return p;
- // armt_tail:
- // if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; } return lim;
- // return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2));
- // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));
- // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT)
- // #define BR_IA64_NO_INLINE
- Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)
- {
- // Byte *p = data;
- const Byte *lim;
- size &= ~(SizeT)15;
- lim = p + size;
- pc -= 1 << 4;
- pc >>= 4 - 1;
- // pc -= 1 << 1;
-
- for (;;)
- {
- unsigned m;
- for (;;)
- {
- if Z7_UNLIKELY(p == lim)
- return p;
- m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e));
- p += 16;
- pc += 1 << 1;
- if (m &= 3)
- break;
- }
- {
- p += (ptrdiff_t)m * 5 - 20; // negative value is expected here.
- do
- {
- const UInt32 t =
- #if defined(MY_CPU_X86_OR_AMD64)
- // we use 32-bit load here to reduce code size on x86:
- GetUi32(p);
- #else
- GetUi16(p);
- #endif
- UInt32 z = GetUi32(p + 1) >> m;
- p += 5;
- if (((t >> m) & (0x70 << 1)) == 0
- && ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0)
- {
- UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z;
- z ^= v;
- #ifdef BR_IA64_NO_INLINE
- v |= (v & ((UInt32)1 << (23 + 1))) >> 3;
- {
- UInt32 c = pc;
- BR_CONVERT_VAL(v, c)
- }
- v &= (0x1fffff << 1) | 1;
- #else
- {
- if (encoding)
- {
- // pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits
- pc &= (0x1fffff << 1) | 1;
- v += pc;
- }
- else
- {
- // pc |= 0xc00000 << 1; // we need to set at least 2 bits
- pc |= ~(UInt32)((0x1fffff << 1) | 1);
- v -= pc;
- }
- }
- v &= ~(UInt32)(0x600000 << 1);
- #endif
- v += (0x700000 << 1);
- v &= (0x8fffff << 1) | 1;
- z |= v;
- z <<= m;
- SetUi32(p + 1 - 5, z)
- }
- m++;
- }
- while (m &= 3); // while (m < 4);
- }
- }
- }
- Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)
- #define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;
- #define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;
- #if 1 && defined(MY_CPU_LE_UNALIGN)
- #define RISCV_USE_UNALIGNED_LOAD
- #endif
- #ifdef RISCV_USE_UNALIGNED_LOAD
- #define RISCV_GET_UI32(p) GetUi32(p)
- #define RISCV_SET_UI32(p, v) { SetUi32(p, v) }
- #else
- #define RISCV_GET_UI32(p) \
- ((UInt32)GetUi16a(p) + \
- ((UInt32)GetUi16a((p) + 2) << 16))
- #define RISCV_SET_UI32(p, v) { \
- SetUi16a(p, (UInt16)(v)) \
- SetUi16a((p) + 2, (UInt16)(v >> 16)) }
- #endif
- #if 1 && defined(MY_CPU_LE)
- #define RISCV_USE_16BIT_LOAD
- #endif
- #ifdef RISCV_USE_16BIT_LOAD
- #define RISCV_LOAD_VAL(p) GetUi16a(p)
- #else
- #define RISCV_LOAD_VAL(p) (*(p))
- #endif
- #define RISCV_INSTR_SIZE 2
- #define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)
- #define RISCV_STEP_2 4
- #define RISCV_REG_VAL (2 << 7)
- #define RISCV_CMD_VAL 3
- #if 1
- // for code size optimization:
- #define RISCV_DELTA_7F 0x7f
- #else
- #define RISCV_DELTA_7F 0
- #endif
- #define RISCV_CHECK_1(v, b) \
- (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)
- #if 1
- #define RISCV_CHECK_2(v, r) \
- ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \
- << 18) \
- < ((r) & 0x1d))
- #else
- // this branch gives larger code, because
- // compilers generate larger code for big constants.
- #define RISCV_CHECK_2(v, r) \
- ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
- & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
- < ((r) & 0x1d))
- #endif
- #define RISCV_SCAN_LOOP \
- Byte *lim; \
- size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \
- if (size <= 6) return p; \
- size -= 6; \
- lim = p + size; \
- BR_PC_INIT \
- for (;;) \
- { \
- UInt32 a, v; \
- /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \
- for (;;) \
- { \
- if Z7_UNLIKELY(p >= lim) { return p; } \
- a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \
- if ((a & 0x77) == 0) break; \
- a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \
- p += RISCV_INSTR_SIZE * 2; \
- if ((a & 0x77) == 0) \
- { \
- p -= RISCV_INSTR_SIZE; \
- if Z7_UNLIKELY(p >= lim) { return p; } \
- break; \
- } \
- }
- // (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL
- // (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL
- // (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC
- // (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC
- Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)
- {
- RISCV_SCAN_LOOP
- v = a;
- a = RISCV_GET_UI32(p);
- #ifndef RISCV_USE_16BIT_LOAD
- v += (UInt32)p[1] << 8;
- #endif
- if ((v & 8) == 0) // JAL
- {
- if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)
- {
- p += RISCV_INSTR_SIZE;
- continue;
- }
- {
- v = ((a & 1u << 31) >> 11)
- | ((a & 0x3ff << 21) >> 20)
- | ((a & 1 << 20) >> 9)
- | (a & 0xff << 12);
- BR_CONVERT_VAL_ENC(v)
- // ((v & 1) == 0)
- // v: bits [1 : 20] contain offset bits
- #if 0 && defined(RISCV_USE_UNALIGNED_LOAD)
- a &= 0xfff;
- a |= ((UInt32)(v << 23))
- | ((UInt32)(v << 7) & ((UInt32)0xff << 16))
- | ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));
- RISCV_SET_UI32(p, a)
- #else // aligned
- #if 0
- SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))
- #else
- p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));
- #endif
- #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
- v <<= 15;
- v = Z7_BSWAP32(v);
- SetUi16a(p + 2, (UInt16)v)
- #else
- p[2] = (Byte)(v >> 9);
- p[3] = (Byte)(v >> 1);
- #endif
- #endif // aligned
- }
- p += 4;
- continue;
- } // JAL
- {
- // AUIPC
- if (v & 0xe80) // (not x0) and (not x2)
- {
- const UInt32 b = RISCV_GET_UI32(p + 4);
- if (RISCV_CHECK_1(v, b))
- {
- {
- const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);
- RISCV_SET_UI32(p, temp)
- }
- a &= 0xfffff000;
- {
- #if 1
- const int t = -1 >> 1;
- if (t != -1)
- a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation
- else
- #endif
- a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).
- }
- BR_CONVERT_VAL_ENC(a)
- #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
- a = Z7_BSWAP32(a);
- RISCV_SET_UI32(p + 4, a)
- #else
- SetBe32(p + 4, a)
- #endif
- p += 8;
- }
- else
- p += RISCV_STEP_1;
- }
- else
- {
- UInt32 r = a >> 27;
- if (RISCV_CHECK_2(v, r))
- {
- v = RISCV_GET_UI32(p + 4);
- r = (r << 7) + 0x17 + (v & 0xfffff000);
- a = (a >> 12) | (v << 20);
- RISCV_SET_UI32(p, r)
- RISCV_SET_UI32(p + 4, a)
- p += 8;
- }
- else
- p += RISCV_STEP_2;
- }
- }
- } // for
- }
- Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)
- {
- RISCV_SCAN_LOOP
- #ifdef RISCV_USE_16BIT_LOAD
- if ((a & 8) == 0)
- {
- #else
- v = a;
- a += (UInt32)p[1] << 8;
- if ((v & 8) == 0)
- {
- #endif
- // JAL
- a -= 0x100 - RISCV_DELTA_7F;
- if (a & 0xd80)
- {
- p += RISCV_INSTR_SIZE;
- continue;
- }
- {
- const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;
- #if 0 // unaligned
- a = GetUi32(p);
- v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)
- | (UInt32)(a >> 7) & ((UInt32)0xff << 9)
- #elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
- v = GetUi16a(p + 2);
- v = Z7_BSWAP32(v) >> 15
- #else
- v = (UInt32)p[3] << 1
- | (UInt32)p[2] << 9
- #endif
- | (UInt32)((a & 0xf000) << 5);
- BR_CONVERT_VAL_DEC(v)
- a = a_old
- | (v << 11 & 1u << 31)
- | (v << 20 & 0x3ff << 21)
- | (v << 9 & 1 << 20)
- | (v & 0xff << 12);
- RISCV_SET_UI32(p, a)
- }
- p += 4;
- continue;
- } // JAL
- {
- // AUIPC
- v = a;
- #if 1 && defined(RISCV_USE_UNALIGNED_LOAD)
- a = GetUi32(p);
- #else
- a |= (UInt32)GetUi16a(p + 2) << 16;
- #endif
- if ((v & 0xe80) == 0) // x0/x2
- {
- const UInt32 r = a >> 27;
- if (RISCV_CHECK_2(v, r))
- {
- UInt32 b;
- #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
- b = RISCV_GET_UI32(p + 4);
- b = Z7_BSWAP32(b);
- #else
- b = GetBe32(p + 4);
- #endif
- v = a >> 12;
- BR_CONVERT_VAL_DEC(b)
- a = (r << 7) + 0x17;
- a += (b + 0x800) & 0xfffff000;
- v |= b << 20;
- RISCV_SET_UI32(p, a)
- RISCV_SET_UI32(p + 4, v)
- p += 8;
- }
- else
- p += RISCV_STEP_2;
- }
- else
- {
- const UInt32 b = RISCV_GET_UI32(p + 4);
- if (!RISCV_CHECK_1(v, b))
- p += RISCV_STEP_1;
- else
- {
- v = (a & 0xfffff000) | (b >> 20);
- a = (b << 12) | (0x17 + RISCV_REG_VAL);
- RISCV_SET_UI32(p, a)
- RISCV_SET_UI32(p + 4, v)
- p += 8;
- }
- }
- }
- } // for
- }
|