From a9269613e90ab03b3b2bf6e7512171831d3b926e Mon Sep 17 00:00:00 2001 From: David Hinault Date: Wed, 19 Aug 2026 08:52:26 +0200 Subject: [PATCH 1/2] xtensa: add SALT/SALTU opcodes to esp32/esp32s3 core 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). --- arch/xtensa/core-esp32/xtensa-modules.c.inc | 49 +++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/arch/xtensa/core-esp32/xtensa-modules.c.inc b/arch/xtensa/core-esp32/xtensa-modules.c.inc index 0d7e51e6d..c03ea306a 100644 --- a/arch/xtensa/core-esp32/xtensa-modules.c.inc +++ b/arch/xtensa/core-esp32/xtensa-modules.c.inc @@ -7214,6 +7214,12 @@ static xtensa_arg_internal Iclass_xt_mul32_args[] = { { { OPERAND_art }, 'i' } }; +static xtensa_arg_internal Iclass_xt_iclass_salt_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + static xtensa_arg_internal Iclass_xt_mul32h_args[] = { { { OPERAND_arr }, 'o' }, { { OPERAND_ars }, 'i' }, @@ -9234,7 +9240,9 @@ static xtensa_iclass_internal iclasses[] = { { 1, Iclass_iclass_CLRB_EXPSTATE_args, 1, Iclass_iclass_CLRB_EXPSTATE_stateArgs, 0, 0 }, { 2, Iclass_iclass_WRMSK_EXPSTATE_args, - 1, Iclass_iclass_WRMSK_EXPSTATE_stateArgs, 0, 0 } + 1, Iclass_iclass_WRMSK_EXPSTATE_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_salt_args, + 0, 0, 0, 0 } }; enum xtensa_iclass_id { @@ -9627,7 +9635,8 @@ enum xtensa_iclass_id { ICLASS_iclass_READ_IMPWIRE, ICLASS_iclass_SETB_EXPSTATE, ICLASS_iclass_CLRB_EXPSTATE, - ICLASS_iclass_WRMSK_EXPSTATE + ICLASS_iclass_WRMSK_EXPSTATE, + ICLASS_xt_iclass_salt }; @@ -12171,6 +12180,18 @@ Opcode_andb_Slot_inst_encode (xtensa_insnbuf slotbuf) slotbuf[0] = 0x20000; } +static void +Opcode_salt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x720000; +} + +static void +Opcode_saltu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x620000; +} + static void Opcode_andbc_Slot_inst_encode (xtensa_insnbuf slotbuf) { @@ -14403,6 +14424,14 @@ static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = { Opcode_andb_Slot_inst_encode, 0, 0 }; +static xtensa_opcode_encode_fn Opcode_salt_encode_fns[] = { + Opcode_salt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_saltu_encode_fns[] = { + Opcode_saltu_Slot_inst_encode, 0, 0 +}; + static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = { Opcode_andbc_Slot_inst_encode, 0, 0 }; @@ -16306,7 +16335,13 @@ static xtensa_opcode_internal opcodes[] = { Opcode_clrb_expstate_encode_fns, 0, 0 }, { "wrmsk_expstate", ICLASS_iclass_WRMSK_EXPSTATE, 0, - Opcode_wrmsk_expstate_encode_fns, 0, 0 } + Opcode_wrmsk_expstate_encode_fns, 0, 0 }, + { "salt", ICLASS_xt_iclass_salt, + 0, + Opcode_salt_encode_fns, 0, 0 }, + { "saltu", ICLASS_xt_iclass_salt, + 0, + Opcode_saltu_encode_fns, 0, 0 } }; enum xtensa_opcode_id { @@ -16822,7 +16857,9 @@ enum xtensa_opcode_id { OPCODE_READ_IMPWIRE, OPCODE_SETB_EXPSTATE, OPCODE_CLRB_EXPSTATE, - OPCODE_WRMSK_EXPSTATE + OPCODE_WRMSK_EXPSTATE, + OPCODE_SALT, + OPCODE_SALTU }; @@ -17196,6 +17233,10 @@ Slot_inst_decode (const xtensa_insnbuf insn) return OPCODE_ORBC; if (Field_op2_Slot_inst_get (insn) == 4) return OPCODE_XORB; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_SALTU; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_SALT; if (Field_op2_Slot_inst_get (insn) == 8) return OPCODE_MULL; if (Field_op2_Slot_inst_get (insn) == 10) From 1b13873f8d93d32e5c061d79daceb6141a32031e Mon Sep 17 00:00:00 2001 From: David Hinault Date: Wed, 19 Aug 2026 09:48:06 +0200 Subject: [PATCH 2/2] xtensa: bump esp32 core opcode/iclass counts for new SALT/SALTU entries 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. --- arch/xtensa/core-esp32/xtensa-modules.c.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/xtensa/core-esp32/xtensa-modules.c.inc b/arch/xtensa/core-esp32/xtensa-modules.c.inc index c03ea306a..a6d489142 100644 --- a/arch/xtensa/core-esp32/xtensa-modules.c.inc +++ b/arch/xtensa/core-esp32/xtensa-modules.c.inc @@ -19221,8 +19221,8 @@ xtensa_isa_internal xtensa_modules = { 3, slots, 83 /* num_fields */, 140, operands, - 390, iclasses, - 513, opcodes, 0, + 391, iclasses, + 515, opcodes, 0, 8, regfiles, NUM_STATES, states, 0, NUM_SYSREGS, sysregs, 0,