Skip to content

xtensa: add SALT/SALTU opcodes to esp32/esp32s3 core - #41

Open
hinaultd wants to merge 2 commits into
antmicro:masterfrom
hinaultd:esp32-add-salt-saltu-opcodes
Open

xtensa: add SALT/SALTU opcodes to esp32/esp32s3 core#41
hinaultd wants to merge 2 commits into
antmicro:masterfrom
hinaultd:esp32-add-salt-saltu-opcodes

Conversation

@hinaultd

Copy link
Copy Markdown

Summary

The generic instruction semantics for SALT (Set-A-Less-Than) and SALTU
(Set-A-Less-Than-Unsigned) already exist in translate.c (core_ops[],
.name = "salt"/"saltu", translate_salt), but the esp32 core opcode table
(arch/xtensa/core-esp32/xtensa-modules.c.inc, reused as-is by
core-esp32s3.c) never declares these opcodes, so they are never recognized
by the decoder for this core, and any code using them aborts with
unrecognized opcode in slot 0.

Real-world impact: xtensa-esp32s3-elf-gcc emits SALTU/SALT for the
common range-check idiom (low <= p < high), e.g. in the ESP-IDF
esp_ptr_executable/esp_ptr_in_dram family of helpers. Any ESP32 or
ESP32-S3 firmware exercising these helpers hits the unrecognized-opcode
abort under Renode.

What this adds

Mirrors the entries already present for other cores that support this
instruction (e.g. core-de233_fpu), slotted into the existing op1==2
decode branch used by ANDB/ORB/XORB/MULL/QUOU/etc., which already
handles every other opcode in that group:

  • Iclass_xt_iclass_salt_args[] (3 args: arr out, ars/art in)
  • iclasses[] entry + ICLASS_xt_iclass_salt enum value
  • Opcode_salt_Slot_inst_encode / Opcode_saltu_Slot_inst_encode (encode
    functions, bit patterns identical to the ones already used by cores that
    support this opcode — it is a standard/core Xtensa RRR-format opcode, not
    a config-specific extension)
  • Opcode_salt_encode_fns[] / Opcode_saltu_encode_fns[]
  • opcodes[] name-table entries ("salt", "saltu")
  • OPCODE_SALT / OPCODE_SALTU enum values
  • The two missing Slot_inst_decode branches (op2==6 -> OPCODE_SALTU,
    op2==7 -> OPCODE_SALT) in the existing op1==2 block

Testing

Compiles cleanly with the existing CMake build
(cmake -DTARGET_ARCH=xtensa -DCMAKE_BUILD_TYPE=Release ..), and correctly
decodes/executes saltu a8, a8, a9 instructions from a real ESP32-S3
firmware ELF (traced via esp_ptr_executable) that previously aborted with
unrecognized opcode in slot 0 (pc = 0x403814f0).

I was not able to do a full end-to-end runtime verification against a
locally-built Renode, since the native library ABI expected by my local
Renode install did not match what a from-source tlib build produces
(missing unrelated symbols from a newer/private build) — that is an
environment/build-pinning issue on my end, unrelated to this specific
change. The opcode-table addition itself is otherwise a self-contained,
mechanical patch following the exact pattern already used by other cores
in this same file.

The generic instruction semantics for SALT (Set-A-Less-Than) and
SALTU (Set-A-Less-Than-Unsigned) already exist in translate.c
(core_ops[], .name = "salt"/"saltu", translate_salt), but the
esp32 core opcode table (core-esp32/xtensa-modules.c.inc, reused
as-is by core-esp32s3.c) never declares these opcodes, so they are
never recognized by the decoder for this core and any code using
them aborts with "unrecognized opcode in slot 0".

Real-world impact: xtensa-esp32s3-elf-gcc emits SALTU/SALT for the
common range-check idiom (low <= p < high), e.g. in the ESP-IDF
esp_ptr_executable/esp_ptr_in_dram family of helpers. Any ESP32 or
ESP32-S3 firmware exercising these helpers hits the unrecognized
opcode abort.

This adds the missing table entries (iclass, iclass args, opcode
enum values, name-to-iclass mapping, encode functions, and the
Slot_inst_decode branches for op1==2, op2==6/7) mirroring the
existing entries already present for other cores that support this
instruction (e.g. core-de233_fpu), and slots them into the existing
op1==2 decode branch used by ANDB/ORB/XORB/MULL/QUOU/etc, which
already handles every other opcode in that group.

Verified: the esp32/esp32s3 xtensa-modules.c.inc changes compile
cleanly with the existing CMake build (-DTARGET_ARCH=xtensa).
xtensa_modules.isa_internal (the top-level ISA struct at the end of
xtensa-modules.c.inc) carries the opcodes/iclasses array lengths as
hardcoded literals (390/513), not ARRAY_SIZE() expressions. Adding the
salt/saltu opcode and iclass entries without bumping these two numbers
left them at their old counts, which config->opcode_ops[] (malloc'd
from that same count in helper.c's init_libisa) is sized from. The two
new opcode IDs then indexed past the end of that allocation, reading
garbage XtensaOpcodeOps pointers, observed as a bogus non-zero
ops->coprocessor value that spuriously raised a COPROCESSOR_DISABLED
exception every time SALT/SALTU executed, instead of running them as
plain ALU instructions.

Bumped iclasses 390 -> 391 and opcodes 513 -> 515 to match the one new
iclass and two new opcodes added by the previous commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants