/* ARC header files. */
#include "opcode/arc.h"
+#include "opcodes/arc-dis.h"
#include "arc-tdep.h"
/* Standard headers. */
"lp_count", "reserved", "limm", "pcl",
};
+/* Returns an unsigned value of OPERAND_NUM in instruction INSN.
+ For relative branch instructions returned value is an offset, not an actual
+ branch target. */
+
+static ULONGEST
+arc_insn_get_operand_value (const struct arc_instruction &insn,
+ unsigned int operand_num)
+{
+ switch (insn.operands[operand_num].kind)
+ {
+ case ARC_OPERAND_KIND_LIMM:
+ gdb_assert (insn.limm_p);
+ return insn.limm_value;
+ case ARC_OPERAND_KIND_SHIMM:
+ return insn.operands[operand_num].value;
+ default:
+ /* Value in instruction is a register number. */
+ struct regcache *regcache = get_current_regcache ();
+ ULONGEST value;
+ regcache_cooked_read_unsigned (regcache,
+ insn.operands[operand_num].value,
+ &value);
+ return value;
+ }
+}
+
+/* Like arc_insn_get_operand_value, but returns a signed value. */
+
+static LONGEST
+arc_insn_get_operand_value_signed (const struct arc_instruction &insn,
+ unsigned int operand_num)
+{
+ switch (insn.operands[operand_num].kind)
+ {
+ case ARC_OPERAND_KIND_LIMM:
+ gdb_assert (insn.limm_p);
+ /* Convert unsigned raw value to signed one. This assumes 2's
+ complement arithmetic, but so is the LONG_MIN value from generic
+ defs.h and that assumption is true for ARC. */
+ gdb_static_assert (sizeof (insn.limm_value) == sizeof (int));
+ return (((LONGEST) insn.limm_value) ^ INT_MIN) - INT_MIN;
+ case ARC_OPERAND_KIND_SHIMM:
+ /* Sign conversion has been done by binutils. */
+ return insn.operands[operand_num].value;
+ default:
+ /* Value in instruction is a register number. */
+ struct regcache *regcache = get_current_regcache ();
+ LONGEST value;
+ regcache_cooked_read_signed (regcache,
+ insn.operands[operand_num].value,
+ &value);
+ return value;
+ }
+}
+
+/* Get register with base address of memory operation. */
+
+int
+arc_insn_get_memory_base_reg (const struct arc_instruction &insn)
+{
+ /* POP_S and PUSH_S have SP as an implicit argument in a disassembler. */
+ if (insn.insn_class == PUSH || insn.insn_class == POP)
+ return ARC_SP_REGNUM;
+
+ gdb_assert (insn.insn_class == LOAD || insn.insn_class == STORE);
+
+ /* Other instructions all have at least two operands: operand 0 is data,
+ operand 1 is address. Operand 2 is offset from address. However, see
+ comment to arc_instruction.operands - in some cases, third operand may be
+ missing, namely if it is 0. */
+ gdb_assert (insn.operands_count >= 2);
+ return insn.operands[1].value;
+}
+
+/* Get offset of a memory operation INSN. */
+
+CORE_ADDR
+arc_insn_get_memory_offset (const struct arc_instruction &insn)
+{
+ /* POP_S and PUSH_S have offset as an implicit argument in a
+ disassembler. */
+ if (insn.insn_class == POP)
+ return 4;
+ else if (insn.insn_class == PUSH)
+ return -4;
+
+ gdb_assert (insn.insn_class == LOAD || insn.insn_class == STORE);
+
+ /* Other instructions all have at least two operands: operand 0 is data,
+ operand 1 is address. Operand 2 is offset from address. However, see
+ comment to arc_instruction.operands - in some cases, third operand may be
+ missing, namely if it is 0. */
+ if (insn.operands_count < 3)
+ return 0;
+
+ CORE_ADDR value = arc_insn_get_operand_value (insn, 2);
+ /* Handle scaling. */
+ if (insn.writeback_mode == ARC_WRITEBACK_AS)
+ {
+ /* Byte data size is not valid for AS. Halfword means shift by 1 bit.
+ Word and double word means shift by 2 bits. */
+ gdb_assert (insn.data_size_mode != ARC_SCALING_B);
+ if (insn.data_size_mode == ARC_SCALING_H)
+ value <<= 1;
+ else
+ value <<= 2;
+ }
+ return value;
+}
+
+/* Functions are sorted in the order as they are used in the
+ _initialize_arc_tdep (), which uses the same order as gdbarch.h. Static
+ functions are defined before the first invocation. */
+
+CORE_ADDR
+arc_insn_get_branch_target (const struct arc_instruction &insn)
+{
+ gdb_assert (insn.is_control_flow);
+
+ /* BI [c]: PC = nextPC + (c << 2). */
+ if (insn.insn_class == BI)
+ {
+ ULONGEST reg_value = arc_insn_get_operand_value (insn, 0);
+ return arc_insn_get_linear_next_pc (insn) + (reg_value << 2);
+ }
+ /* BIH [c]: PC = nextPC + (c << 1). */
+ else if (insn.insn_class == BIH)
+ {
+ ULONGEST reg_value = arc_insn_get_operand_value (insn, 0);
+ return arc_insn_get_linear_next_pc (insn) + (reg_value << 1);
+ }
+ /* JLI and EI. */
+ /* JLI and EI depend on optional AUX registers. Not supported right now. */
+ else if (insn.insn_class == JLI)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "JLI_S instruction is not supported by the GDB.");
+ return 0;
+ }
+ else if (insn.insn_class == EI)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "EI_S instruction is not supported by the GDB.");
+ return 0;
+ }
+ /* LEAVE_S: PC = BLINK. */
+ else if (insn.insn_class == LEAVE)
+ {
+ struct regcache *regcache = get_current_regcache ();
+ ULONGEST value;
+ regcache_cooked_read_unsigned (regcache, ARC_BLINK_REGNUM, &value);
+ return value;
+ }
+ /* BBIT0/1, BRcc: PC = currentPC + operand. */
+ else if (insn.insn_class == BBIT0 || insn.insn_class == BBIT1
+ || insn.insn_class == BRCC)
+ {
+ /* Most instructions has branch target as their sole argument. However
+ conditional brcc/bbit has it as a third operand. */
+ CORE_ADDR pcrel_addr = arc_insn_get_operand_value (insn, 2);
+
+ /* Offset is relative to the 4-byte aligned address of the current
+ instruction, hence last two bits should be truncated. */
+ return pcrel_addr + align_down (insn.address, 4);
+ }
+ /* B, Bcc, BL, BLcc, LP, LPcc: PC = currentPC + operand. */
+ else if (insn.insn_class == BRANCH || insn.insn_class == LOOP)
+ {
+ CORE_ADDR pcrel_addr = arc_insn_get_operand_value (insn, 0);
+
+ /* Offset is relative to the 4-byte aligned address of the current
+ instruction, hence last two bits should be truncated. */
+ return pcrel_addr + align_down (insn.address, 4);
+ }
+ /* J, Jcc, JL, JLcc: PC = operand. */
+ else if (insn.insn_class == JUMP)
+ {
+ /* All jumps are single-operand. */
+ return arc_insn_get_operand_value (insn, 0);
+ }
+
+ /* This is some new and unknown instruction. */
+ gdb_assert_not_reached ("Unknown branch instruction.");
+}
+
+/* Dump INSN into gdb_stdlog. */
+
+void
+arc_insn_dump (const struct arc_instruction &insn)
+{
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ arc_print ("Dumping arc_instruction at %s\n",
+ paddress (gdbarch, insn.address));
+ arc_print ("\tlength = %u\n", insn.length);
+
+ if (!insn.valid)
+ {
+ arc_print ("\tThis is not a valid ARC instruction.\n");
+ return;
+ }
+
+ arc_print ("\tlength_with_limm = %u\n", insn.length + (insn.limm_p ? 4 : 0));
+ arc_print ("\tcc = 0x%x\n", insn.condition_code);
+ arc_print ("\tinsn_class = %u\n", insn.insn_class);
+ arc_print ("\tis_control_flow = %i\n", insn.is_control_flow);
+ arc_print ("\thas_delay_slot = %i\n", insn.has_delay_slot);
+
+ CORE_ADDR next_pc = arc_insn_get_linear_next_pc (insn);
+ arc_print ("\tlinear_next_pc = %s\n", paddress (gdbarch, next_pc));
+
+ if (insn.is_control_flow)
+ {
+ CORE_ADDR t = arc_insn_get_branch_target (insn);
+ arc_print ("\tbranch_target = %s\n", paddress (gdbarch, t));
+ }
+
+ arc_print ("\tlimm_p = %i\n", insn.limm_p);
+ if (insn.limm_p)
+ arc_print ("\tlimm_value = 0x%08x\n", insn.limm_value);
+
+ if (insn.insn_class == STORE || insn.insn_class == LOAD
+ || insn.insn_class == PUSH || insn.insn_class == POP)
+ {
+ arc_print ("\twriteback_mode = %u\n", insn.writeback_mode);
+ arc_print ("\tdata_size_mode = %u\n", insn.data_size_mode);
+ arc_print ("\tmemory_base_register = %s\n",
+ gdbarch_register_name (gdbarch,
+ arc_insn_get_memory_base_reg (insn)));
+ /* get_memory_offset returns an unsigned CORE_ADDR, but treat it as a
+ LONGEST for a nicer representation. */
+ arc_print ("\taddr_offset = %s\n",
+ plongest (arc_insn_get_memory_offset (insn)));
+ }
+
+ arc_print ("\toperands_count = %u\n", insn.operands_count);
+ for (unsigned int i = 0; i < insn.operands_count; ++i)
+ {
+ int is_reg = (insn.operands[i].kind == ARC_OPERAND_KIND_REG);
+
+ arc_print ("\toperand[%u] = {\n", i);
+ arc_print ("\t\tis_reg = %i\n", is_reg);
+ if (is_reg)
+ arc_print ("\t\tregister = %s\n",
+ gdbarch_register_name (gdbarch, insn.operands[i].value));
+ /* Don't know if this value is signed or not, so print both
+ representations. This tends to look quite ugly, especially for big
+ numbers. */
+ arc_print ("\t\tunsigned value = %s\n",
+ pulongest (arc_insn_get_operand_value (insn, i)));
+ arc_print ("\t\tsigned value = %s\n",
+ plongest (arc_insn_get_operand_value_signed (insn, i)));
+ arc_print ("\t}\n");
+ }
+}
+
+CORE_ADDR
+arc_insn_get_linear_next_pc (const struct arc_instruction &insn)
+{
+ /* In ARC long immediate is always 4 bytes. */
+ return (insn.address + insn.length + (insn.limm_p ? 4 : 0));
+}
+
/* Implement the "write_pc" gdbarch method.
In ARC PC register is a normal register so in most cases setting PC value
return (CORE_ADDR) get_frame_register_unsigned (this_frame, ARC_FP_REGNUM);
}
+/* Copy of gdb_buffered_insn_length_fprintf from disasm.c. */
+
+static int ATTRIBUTE_PRINTF (2, 3)
+arc_fprintf_disasm (void *stream, const char *format, ...)
+{
+ return 0;
+}
+
+struct disassemble_info
+arc_disassemble_info (struct gdbarch *gdbarch)
+{
+ struct disassemble_info di;
+ init_disassemble_info (&di, &null_stream, arc_fprintf_disasm);
+ di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
+ di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
+ di.endian = gdbarch_byte_order (gdbarch);
+ di.read_memory_func = [](bfd_vma memaddr, gdb_byte *myaddr,
+ unsigned int len, struct disassemble_info *info)
+ {
+ return target_read_code (memaddr, myaddr, len);
+ };
+ return di;
+}
+
/* Implement the "skip_prologue" gdbarch method.
Skip the prologue for the function at PC. This is done by checking from
that will not print, or `stream` should be different from standard
gdb_stdlog. */
-static int
+int
arc_delayed_print_insn (bfd_vma addr, struct disassemble_info *info)
{
int (*print_insn) (bfd_vma, struct disassemble_info *);
cmd_show_list (maintenance_print_arc_list, from_tty, "");
}
+/* This command accepts single argument - address of instruction to
+ disassemble. */
+
+static void
+dump_arc_instruction_command (char *args, int from_tty)
+{
+ struct value *val;
+ if (args != NULL && strlen (args) > 0)
+ val = evaluate_expression (parse_expression (args).get ());
+ else
+ val = access_value_history (0);
+ record_latest_value (val);
+
+ CORE_ADDR address = value_as_address (val);
+ struct arc_instruction insn;
+ struct disassemble_info di = arc_disassemble_info (target_gdbarch ());
+ arc_insn_decode (address, &di, arc_delayed_print_insn, &insn);
+ arc_insn_dump (insn);
+}
+
/* Suppress warning from -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_arc_tdep;
&maintenance_print_arc_list, "maintenance print arc ", 0,
&maintenanceprintlist);
+ add_cmd ("arc-instruction", class_maintenance,
+ dump_arc_instruction_command,
+ _("Dump arc_instruction structure for specified address."),
+ &maintenance_print_arc_list);
+
/* Debug internals for ARC GDB. */
add_setshow_zinteger_cmd ("arc", class_maintenance,
&arc_debug,
--- /dev/null
+; This testcase is part of GDB, the GNU debugger.
+
+; Copyright 2017 Free Software Foundation, Inc.
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 3 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+.section .text
+.global main
+
+#define TEST_J
+#define TEST_JCC
+#define TEST_JL
+#define TEST_JLCC
+#define TEST_B
+#define TEST_BBIT
+#define TEST_BCC
+#define TEST_BI
+#define TEST_BL
+#define TEST_BRCC
+#define TEST_JLI
+#define TEST_LEAVE_S
+#define TEST_LPCC
+
+; JLI-specific stuff
+#ifdef TEST_JLI
+jli_table:
+ .word 0xdeadbeea
+ .word 0xdeadbeea
+jli_target:
+ .word 0xdeadbeea
+ .word 0xdeadbeea
+
+.set jli_offset, 3
+#endif
+main:
+
+; Each test case requires several symbols to be set, that identify expected
+; parameters of this instruction. Required symbols:
+; ${test}_start: symbol points to start of the test
+; ${test}_end: symbol points to the instruction after the jump/branch
+; instruction.
+; ${test}_target: branch target address.
+; ${test}_has_delay_slot: whether instruction has delay slot.
+; ${test}_cc: condition code numeric value.
+
+ .set r12_value, 0xdead0000
+ .set blink_value, 0xdead0004
+ .set limm_value, 0xdead0008
+ ; Just an integer
+ .set r4_value, 0xdead000c
+ ; Just an integer
+ .set r5_value, 0xdead0010
+ ; offset index for BI [c]
+ .set r7_value, 4
+ .set u6_value, 0x20
+ .set s12_target, 0x100
+
+ mov r12, @r12_value
+ mov r4, @r4_value
+ mov r5, @r5_value
+ mov r7, @r7_value
+ mov blink, @blink_value
+#ifdef TEST_JLI
+ ; jli_base aux regnum = 0x290
+ sr jli_table, [0x290]
+#endif
+
+start_branch_tests:
+
+#ifdef TEST_J
+
+#define TEST_NAME j_c
+ ; j [c]
+ .set j_c_target, @r4_value
+ .set j_c_has_delay_slot, 0
+ .set j_c_cc, 0
+ j_c_start:
+ j [r4]
+ j_c_end:
+
+ ; j [blink]
+ .set j_blink_target, @blink_value
+ .set j_blink_has_delay_slot, 0
+ .set j_blink_cc, 0
+ mov blink, @j_blink_target
+ j_blink_start:
+ j [blink]
+ j_blink_end:
+
+ ; j limm
+ .set j_limm_target, @limm_value
+ .set j_limm_has_delay_slot, 0
+ .set j_limm_cc, 0
+ j_limm_start:
+ j @j_limm_target
+ j_limm_end:
+
+ ; j u6
+ .set j_u6_target, @u6_value
+ .set j_u6_has_delay_slot, 0
+ .set j_u6_cc, 0
+ j_u6_start:
+ j @j_u6_target
+ j_u6_end:
+
+ ; j s12
+ .set j_s12_target, @s12_target
+ .set j_s12_has_delay_slot, 0
+ .set j_s12_cc, 0
+ j_s12_start:
+ j @j_s12_target
+ j_s12_end:
+
+ ; j.d [c]
+ .set j_d_c_target, @r4_value
+ .set j_d_c_has_delay_slot, 1
+ .set j_d_c_cc, 0
+ j_d_c_start:
+ j.d [r4]
+ j_d_c_end:
+ nop_s
+
+ ; j.d [blink]
+ .set j_d_blink_target, @blink_value
+ .set j_d_blink_has_delay_slot, 1
+ .set j_d_blink_cc, 0
+ j_d_blink_start:
+ j.d [blink]
+ j_d_blink_end:
+ nop_s
+
+ ; j.d u6
+ .set j_d_u6_target, @u6_value
+ .set j_d_u6_has_delay_slot, 1
+ .set j_d_u6_cc, 0
+ j_d_u6_start:
+ j.d @j_d_u6_target
+ j_d_u6_end:
+ nop_s
+
+ ; j.d s12
+ .set j_d_s12_target, @s12_target
+ .set j_d_s12_has_delay_slot, 1
+ .set j_d_s12_cc, 0
+ j_d_s12_start:
+ j.d @j_d_s12_target
+ j_d_s12_end:
+ nop_s
+
+ ; j_s [b]
+ .set j_s_b_target, @r12_value
+ .set j_s_b_has_delay_slot, 0
+ .set j_s_b_cc, 0
+ j_s_b_start:
+ j_s [r12]
+ j_s_b_end:
+
+ ; j_s.d [b]
+ .set j_s_d_b_target, @r12_value
+ .set j_s_d_b_has_delay_slot, 1
+ .set j_s_d_b_cc, 0
+ j_s_d_b_start:
+ j_s.d [r12]
+ j_s_d_b_end:
+ nop_s
+
+ ; j_s [blink]
+ .set j_s_blink_target, @blink_value
+ .set j_s_blink_has_delay_slot, 0
+ .set j_s_blink_cc, 0
+ j_s_blink_start:
+ j_s [blink]
+ j_s_blink_end:
+
+ ; j_s.d [blink]
+ .set j_s_d_blink_target, @blink_value
+ .set j_s_d_blink_has_delay_slot, 1
+ .set j_c_cc, 0
+ j_s_d_blink_start:
+ j_s.d [blink]
+ j_s_d_blink_end:
+ nop_s
+#endif /* TEST_J */
+
+#ifdef TEST_JCC
+ ; jcc [c]
+ .set jcc_c_target, @r4_value
+ .set jcc_c_has_delay_slot, 0
+ .set jcc_c_cc, 1
+ jcc_c_start:
+ jeq [r4]
+ jcc_c_end:
+
+ ; jcc [blink]
+ .set jcc_blink_target, @blink_value
+ .set jcc_blink_has_delay_slot, 0
+ .set jcc_blink_cc, 2
+ jcc_blink_start:
+ jnz [blink]
+ jcc_blink_end:
+
+ ; jcc limm
+ .set jcc_limm_target, @limm_value
+ .set jcc_limm_has_delay_slot, 0
+ .set jcc_limm_cc, 9
+ jcc_limm_start:
+ jgt @jcc_limm_target
+ jcc_limm_end:
+
+ ; jcc u6
+ .set jcc_u6_target, @u6_value
+ .set jcc_u6_has_delay_slot, 0
+ .set jcc_u6_cc, 0xA
+ jcc_u6_start:
+ jge @jcc_u6_target
+ jcc_u6_end:
+
+ ; jcc.d [c]
+ .set jcc_d_c_target, @r4_value
+ .set jcc_d_c_has_delay_slot, 1
+ .set jcc_d_c_cc, 0xB
+ jcc_d_c_start:
+ jlt.d [r4]
+ jcc_d_c_end:
+ nop_s
+
+ ; jcc.d [blink]
+ .set jcc_d_blink_target, @blink_value
+ .set jcc_d_blink_has_delay_slot, 1
+ .set jcc_d_blink_cc, 0xC
+ jcc_d_blink_start:
+ jle.d [blink]
+ jcc_d_blink_end:
+ nop_s
+
+ ; jcc.d u6
+ .set jcc_d_u6_target, @u6_value
+ .set jcc_d_u6_has_delay_slot, 1
+ .set jcc_d_u6_cc, 0xE
+ jcc_d_u6_start:
+ jls.d @jcc_d_u6_target
+ jcc_d_u6_end:
+ nop_s
+
+ ; jeq_s [blink]
+ .set jcc_eq_s_blink_target, @blink_value
+ .set jcc_eq_s_blink_has_delay_slot, 0
+ .set jcc_eq_s_blink_cc, 1
+ jcc_eq_s_blink_start:
+ jeq_s [blink]
+ jcc_eq_s_blink_end:
+
+ ; jne_s [blink]
+ .set jcc_ne_s_blink_target, @blink_value
+ .set jcc_ne_s_blink_has_delay_slot, 0
+ .set jcc_ne_s_blink_cc, 2
+ jcc_ne_s_blink_start:
+ jne_s [blink]
+ jcc_ne_s_blink_end:
+#endif /* TEST_JCC */
+
+#ifdef TEST_JL
+ ; jl [c]
+ .set jl_c_target, @r4_value
+ .set jl_c_has_delay_slot, 0
+ .set jl_c_cc, 0
+ jl_c_start:
+ jl [r4]
+ jl_c_end:
+
+ ; jl limm
+ .set jl_limm_target, @limm_value
+ .set jl_limm_has_delay_slot, 0
+ .set jl_limm_cc, 0
+ jl_limm_start:
+ jl @jl_limm_target
+ jl_limm_end:
+
+ ; jl u6
+ .set jl_u6_target, @u6_value
+ .set jl_u6_has_delay_slot, 0
+ .set jl_u6_cc, 0
+ jl_u6_start:
+ jl @jl_u6_target
+ jl_u6_end:
+
+ ; jl s12
+ .set jl_s12_target, @s12_target
+ .set jl_s12_has_delay_slot, 0
+ .set jl_s12_cc, 0
+ jl_s12_start:
+ jl @jl_s12_target
+ jl_s12_end:
+
+ ; jl.d [c]
+ .set jl_d_c_target, @r4_value
+ .set jl_d_c_has_delay_slot, 1
+ .set jl_d_c_cc, 0
+ jl_d_c_start:
+ jl.d [r4]
+ jl_d_c_end:
+ nop_s
+
+ ; jl.d u6
+ .set jl_d_u6_target, @u6_value
+ .set jl_d_u6_has_delay_slot, 1
+ .set jl_d_u6_cc, 0
+ jl_d_u6_start:
+ jl.d @jl_d_u6_target
+ jl_d_u6_end:
+ nop_s
+
+ ; jl.d s12
+ .set jl_d_s12_target, @s12_target
+ .set jl_d_s12_has_delay_slot, 1
+ .set jl_d_s12_cc, 0
+ jl_d_s12_start:
+ jl.d @jl_d_s12_target
+ jl_d_s12_end:
+ nop_s
+
+ ; jl_s [b]
+ .set jl_s_b_target, @r12_value
+ .set jl_s_b_has_delay_slot, 0
+ .set jl_s_b_cc, 0
+ jl_s_b_start:
+ jl_s [r12]
+ jl_s_b_end:
+
+ ; jl_s.d [b]
+ .set jl_s_d_b_target, @r12_value
+ .set jl_s_d_b_has_delay_slot, 1
+ .set jl_s_d_b_cc, 0
+ jl_s_d_b_start:
+ jl_s.d [r12]
+ jl_s_d_b_end:
+ nop_s
+#endif /* TEST_JL */
+
+#ifdef TEST_JLCC
+ ; jlcc [c]
+ .set jlcc_c_target, @r4_value
+ .set jlcc_c_has_delay_slot, 0
+ .set jlcc_c_cc, 1
+ jlcc_c_start:
+ jleq [r4]
+ jlcc_c_end:
+
+ ; jlcc limm
+ .set jlcc_limm_target, @limm_value
+ .set jlcc_limm_has_delay_slot, 0
+ .set jlcc_limm_cc, 0x9
+ jlcc_limm_start:
+ jlgt @jlcc_limm_target
+ jlcc_limm_end:
+
+ ; jlcc u6
+ .set jlcc_u6_target, @u6_value
+ .set jlcc_u6_has_delay_slot, 0
+ .set jlcc_u6_cc, 0xA
+ jlcc_u6_start:
+ jlge @jlcc_u6_target
+ jlcc_u6_end:
+
+ ; jlcc.d [c]
+ .set jlcc_d_c_target, @r4_value
+ .set jlcc_d_c_has_delay_slot, 1
+ .set jlcc_d_c_cc, 0xB
+ jlcc_d_c_start:
+ jllt.d [r4]
+ jlcc_d_c_end:
+ nop_s
+
+ ; jlcc.d u6
+ .set jlcc_d_u6_target, @u6_value
+ .set jlcc_d_u6_has_delay_slot, 1
+ .set jlcc_d_u6_cc, 0xE
+ jlcc_d_u6_start:
+ jlls.d @jlcc_d_u6_target
+ jlcc_d_u6_end:
+ nop_s
+#endif /* TEST_JLCC */
+
+#ifdef TEST_B
+.Lb_target:
+ ; Artifical nop, so that first b will not branch to itself.
+ nop_s
+ ; b s25
+ .set b_s25_target, @.Lb_target
+ .set b_s25_has_delay_slot, 0
+ .set b_s25_cc, 0
+ b_s25_start:
+ b @b_s25_target
+ b_s25_end:
+
+ ; b.d s25
+ .set b_d_s25_target, @.Lb_target
+ .set b_d_s25_has_delay_slot, 1
+ .set b_d_s25_cc, 0
+ b_d_s25_start:
+ b.d @b_d_s25_target
+ b_d_s25_end:
+ nop_s
+
+ ; b_s s10
+ .set b_s_s10_target, @.Lb_target
+ .set b_s_s10_has_delay_slot, 0
+ .set b_s_s10_cc, 0
+ b_s_s10_start:
+ b_s @b_s_s10_target
+ b_s_s10_end:
+#endif /* TEST_B */
+
+#ifdef TEST_BBIT
+
+; Due to specifics of bbit implementation in assembler, only local symbols can
+; be used as a branch targets for bbit and brcc.
+; bbits and brcc don't have condition code set to anything.
+.Lbbit_target:
+ nop_s
+
+ ; bbit0.nt b,c,s9
+ .set bbit0_nt_b_c_s9_target, @.Lbbit_target
+ .set bbit0_nt_b_c_s9_has_delay_slot, 0
+ .set bbit0_nt_b_c_s9_cc, 0
+ bbit0_nt_b_c_s9_start:
+ bbit0.nt r4,r5,@bbit0_nt_b_c_s9_target
+ bbit0_nt_b_c_s9_end:
+
+ ; bbit0.d.nt b,c,s9
+ .set bbit0_d_nt_b_c_s9_target, @.Lbbit_target
+ .set bbit0_d_nt_b_c_s9_has_delay_slot, 1
+ .set bbit0_d_nt_b_c_s9_cc, 0
+ bbit0_d_nt_b_c_s9_start:
+ bbit0.d.nt r4,r5,@.Lbbit_target
+ bbit0_d_nt_b_c_s9_end:
+ nop_s
+
+ ; bbit0.t b,c,s9
+ .set bbit0_t_b_c_s9_target, @.Lbbit_target
+ .set bbit0_t_b_c_s9_has_delay_slot, 0
+ .set bbit0_t_b_c_s9_cc, 0
+ bbit0_t_b_c_s9_start:
+ bbit0.t r4,r5,@.Lbbit_target
+ bbit0_t_b_c_s9_end:
+
+ ; bbit0.d.t b,c,s9
+ .set bbit0_d_t_b_c_s9_target, @.Lbbit_target
+ .set bbit0_d_t_b_c_s9_has_delay_slot, 1
+ .set bbit0_d_t_b_c_s9_cc, 0
+ bbit0_d_t_b_c_s9_start:
+ bbit0.d.t r4,r5,@.Lbbit_target
+ bbit0_d_t_b_c_s9_end:
+ nop_s
+
+ ; bbit0.nt b,u6,s9
+ .set bbit0_nt_b_u6_s9_target, @.Lbbit_target
+ .set bbit0_nt_b_u6_s9_has_delay_slot, 0
+ .set bbit0_nt_b_u6_s9_cc, 0
+ bbit0_nt_b_u6_s9_start:
+ bbit0.nt r4,u6_value,@.Lbbit_target
+ bbit0_nt_b_u6_s9_end:
+
+ ; bbit0.d.nt b,u6,s9
+ .set bbit0_d_nt_b_u6_s9_target, @.Lbbit_target
+ .set bbit0_d_nt_b_u6_s9_has_delay_slot, 1
+ .set bbit0_d_nt_b_u6_s9_cc, 0
+ bbit0_d_nt_b_u6_s9_start:
+ bbit0.d.nt r4,u6_value,@.Lbbit_target
+ bbit0_d_nt_b_u6_s9_end:
+ nop_s
+
+ ; bbit0.nt b,u6,s9
+ .set bbit0_t_b_u6_s9_target, @.Lbbit_target
+ .set bbit0_t_b_u6_s9_has_delay_slot, 0
+ .set bbit0_t_b_u6_s9_cc, 0
+ bbit0_t_b_u6_s9_start:
+ bbit0.t r4,u6_value,@.Lbbit_target
+ bbit0_t_b_u6_s9_end:
+
+ ; bbit0.d.nt b,u6,s9
+ .set bbit0_d_t_b_u6_s9_target, @.Lbbit_target
+ .set bbit0_d_t_b_u6_s9_has_delay_slot, 1
+ .set bbit0_d_t_b_u6_s9_cc, 0
+ bbit0_d_t_b_u6_s9_start:
+ bbit0.d.t r4,u6_value,@.Lbbit_target
+ bbit0_d_t_b_u6_s9_end:
+ nop_s
+
+ ; bbit0.nt b,limm,s9
+ .set bbit0_nt_b_limm_s9_target, @.Lbbit_target
+ .set bbit0_nt_b_limm_s9_has_delay_slot, 0
+ .set bbit0_nt_b_limm_s9_cc, 0
+ bbit0_nt_b_limm_s9_start:
+ bbit0.nt r4,limm_value,@.Lbbit_target
+ bbit0_nt_b_limm_s9_end:
+
+ ; bbit0.t b,limm,s9
+ .set bbit0_t_b_limm_s9_target, @.Lbbit_target
+ .set bbit0_t_b_limm_s9_has_delay_slot, 0
+ .set bbit0_t_b_limm_s9_cc, 0
+ bbit0_t_b_limm_s9_start:
+ bbit0.t r4,limm_value,@.Lbbit_target
+ bbit0_t_b_limm_s9_end:
+
+ ; bbit0.nt limm,c,s9
+ .set bbit0_nt_limm_c_s9_target, @.Lbbit_target
+ .set bbit0_nt_limm_c_s9_has_delay_slot, 0
+ .set bbit0_nt_limm_c_s9_cc, 0
+ bbit0_nt_limm_c_s9_start:
+ bbit0.nt limm_value,r4,@.Lbbit_target
+ bbit0_nt_limm_c_s9_end:
+
+ ; bbit0.t limm,c,s9
+ .set bbit0_t_limm_c_s9_target, @.Lbbit_target
+ .set bbit0_t_limm_c_s9_has_delay_slot, 0
+ .set bbit0_t_limm_c_s9_cc, 0
+ bbit0_t_limm_c_s9_start:
+ bbit0.t limm_value,r4,@.Lbbit_target
+ bbit0_t_limm_c_s9_end:
+
+ ; bbit0.nt limm,u6,s9
+ .set bbit0_nt_limm_u6_s9_target, @.Lbbit_target
+ .set bbit0_nt_limm_u6_s9_has_delay_slot, 0
+ .set bbit0_nt_limm_u6_s9_cc, 0
+ bbit0_nt_limm_u6_s9_start:
+ bbit0.nt limm_value,u6_value,@.Lbbit_target
+ bbit0_nt_limm_u6_s9_end:
+
+ ; bbit0.t limm,u6,s9
+ .set bbit0_t_limm_u6_s9_target, @.Lbbit_target
+ .set bbit0_t_limm_u6_s9_has_delay_slot, 0
+ .set bbit0_t_limm_u6_s9_cc, 0
+ bbit0_t_limm_u6_s9_start:
+ bbit0.t limm_value,u6_value,@.Lbbit_target
+ bbit0_t_limm_u6_s9_end:
+
+ ; bbit1.nt b,c,s9
+ .set bbit1_nt_b_c_s9_target, @.Lbbit_target
+ .set bbit1_nt_b_c_s9_has_delay_slot, 0
+ .set bbit1_nt_b_c_s9_cc, 0
+ bbit1_nt_b_c_s9_start:
+ bbit1.nt r4,r5,@.Lbbit_target
+ bbit1_nt_b_c_s9_end:
+
+ ; bbit1.d.nt b,c,s9
+ .set bbit1_d_nt_b_c_s9_target, @.Lbbit_target
+ .set bbit1_d_nt_b_c_s9_has_delay_slot, 1
+ .set bbit1_d_nt_b_c_s9_cc, 0
+ bbit1_d_nt_b_c_s9_start:
+ bbit1.d.nt r4,r5,@.Lbbit_target
+ bbit1_d_nt_b_c_s9_end:
+ nop_s
+
+ ; bbit1.t b,c,s9
+ .set bbit1_t_b_c_s9_target, @.Lbbit_target
+ .set bbit1_t_b_c_s9_has_delay_slot, 0
+ .set bbit1_t_b_c_s9_cc, 0
+ bbit1_t_b_c_s9_start:
+ bbit1.t r4,r5,@.Lbbit_target
+ bbit1_t_b_c_s9_end:
+
+ ; bbit1.d.t b,c,s9
+ .set bbit1_d_t_b_c_s9_target, @.Lbbit_target
+ .set bbit1_d_t_b_c_s9_has_delay_slot, 1
+ .set bbit1_d_t_b_c_s9_cc, 0
+ bbit1_d_t_b_c_s9_start:
+ bbit1.d.t r4,r5,@.Lbbit_target
+ bbit1_d_t_b_c_s9_end:
+ nop_s
+
+ ; bbit1.nt b,u6,s9
+ .set bbit1_nt_b_u6_s9_target, @.Lbbit_target
+ .set bbit1_nt_b_u6_s9_has_delay_slot, 0
+ .set bbit1_nt_b_u6_s9_cc, 0
+ bbit1_nt_b_u6_s9_start:
+ bbit1.nt r4,u6_value,@.Lbbit_target
+ bbit1_nt_b_u6_s9_end:
+
+ ; bbit1.d.nt b,u6,s9
+ .set bbit1_d_nt_b_u6_s9_target, @.Lbbit_target
+ .set bbit1_d_nt_b_u6_s9_has_delay_slot, 1
+ .set bbit1_d_nt_b_u6_s9_cc, 0
+ bbit1_d_nt_b_u6_s9_start:
+ bbit1.d.nt r4,u6_value,@.Lbbit_target
+ bbit1_d_nt_b_u6_s9_end:
+ nop_s
+
+ ; bbit1.nt b,u6,s9
+ .set bbit1_t_b_u6_s9_target, @.Lbbit_target
+ .set bbit1_t_b_u6_s9_has_delay_slot, 0
+ .set bbit1_t_b_u6_s9_cc, 0
+ bbit1_t_b_u6_s9_start:
+ bbit1.t r4,u6_value,@.Lbbit_target
+ bbit1_t_b_u6_s9_end:
+
+ ; bbit1.d.nt b,u6,s9
+ .set bbit1_d_t_b_u6_s9_target, @.Lbbit_target
+ .set bbit1_d_t_b_u6_s9_has_delay_slot, 1
+ .set bbit1_d_t_b_u6_s9_cc, 0
+ bbit1_d_t_b_u6_s9_start:
+ bbit1.d.t r4,u6_value,@.Lbbit_target
+ bbit1_d_t_b_u6_s9_end:
+ nop_s
+
+ ; bbit1.nt b,limm,s9
+ .set bbit1_nt_b_limm_s9_target, @.Lbbit_target
+ .set bbit1_nt_b_limm_s9_has_delay_slot, 0
+ .set bbit1_nt_b_limm_s9_cc, 0
+ bbit1_nt_b_limm_s9_start:
+ bbit1.nt r4,limm_value,@.Lbbit_target
+ bbit1_nt_b_limm_s9_end:
+
+ ; bbit1.t b,limm,s9
+ .set bbit1_t_b_limm_s9_target, @.Lbbit_target
+ .set bbit1_t_b_limm_s9_has_delay_slot, 0
+ .set bbit1_t_b_limm_s9_cc, 0
+ bbit1_t_b_limm_s9_start:
+ bbit1.t r4,limm_value,@.Lbbit_target
+ bbit1_t_b_limm_s9_end:
+
+ ; bbit1.nt limm,c,s9
+ .set bbit1_nt_limm_c_s9_target, @.Lbbit_target
+ .set bbit1_nt_limm_c_s9_has_delay_slot, 0
+ .set bbit1_nt_limm_c_s9_cc, 0
+ bbit1_nt_limm_c_s9_start:
+ bbit1.nt limm_value,r4,@.Lbbit_target
+ bbit1_nt_limm_c_s9_end:
+
+ ; bbit1.t limm,c,s9
+ .set bbit1_t_limm_c_s9_target, @.Lbbit_target
+ .set bbit1_t_limm_c_s9_has_delay_slot, 0
+ .set bbit1_t_limm_c_s9_cc, 0
+ bbit1_t_limm_c_s9_start:
+ bbit1.t limm_value,r4,@.Lbbit_target
+ bbit1_t_limm_c_s9_end:
+
+ ; bbit1.nt limm,u6,s9
+ .set bbit1_nt_limm_u6_s9_target, @.Lbbit_target
+ .set bbit1_nt_limm_u6_s9_has_delay_slot, 0
+ .set bbit1_nt_limm_u6_s9_cc, 0
+ bbit1_nt_limm_u6_s9_start:
+ bbit1.nt limm_value,u6_value,@.Lbbit_target
+ bbit1_nt_limm_u6_s9_end:
+
+ ; bbit1.t limm,u6,s9
+ .set bbit1_t_limm_u6_s9_target, @.Lbbit_target
+ .set bbit1_t_limm_u6_s9_has_delay_slot, 0
+ .set bbit1_t_limm_u6_s9_cc, 0
+ bbit1_t_limm_u6_s9_start:
+ bbit1.t limm_value,u6_value,@.Lbbit_target
+ bbit1_t_limm_u6_s9_end:
+#endif /* TEST_BBIT */
+
+#ifdef TEST_BCC
+.Lbcc_target:
+ ; bcc s21
+ .set bcc_s21_target, @.Lbcc_target
+ .set bcc_s21_has_delay_slot, 0
+ .set bcc_s21_cc, 1
+ bcc_s21_start:
+ ; beq @bcc_s21_target
+ beq @.Lbcc_target
+ bcc_s21_end:
+
+ ; bcc.d s21
+ .set bcc_d_s21_target, @.Lbcc_target
+ .set bcc_d_s21_has_delay_slot, 1
+ .set bcc_d_s21_cc, 1
+ bcc_d_s21_start:
+ beq.d @bcc_d_s21_target
+ bcc_d_s21_end:
+ nop_s
+
+.Lbcc_s_target:
+ ; beq_s s10
+ .set beq_s_s10_target, @.Lbcc_s_target
+ .set beq_s_s10_has_delay_slot, 0
+ .set beq_s_s10_cc, 1
+ beq_s_s10_start:
+ # beq_s.d @beq_s_s10_target
+ beq_s @.Lbcc_s_target
+ beq_s_s10_end:
+
+ ; bne_s s10
+ .set bne_s_s10_target, @.Lbcc_s_target
+ .set bne_s_s10_has_delay_slot, 0
+ .set bne_s_s10_cc, 2
+ bne_s_s10_start:
+ bne_s @bne_s_s10_target
+ bne_s_s10_end:
+
+ ; bgt_s s7
+ .set bgt_s_s7_target, @.Lbcc_s_target
+ .set bgt_s_s7_has_delay_slot, 0
+ .set bgt_s_s7_cc, 0x9
+ bgt_s_s7_start:
+ bgt_s @bgt_s_s7_target
+ bgt_s_s7_end:
+
+ ; bge_s s7
+ .set bge_s_s7_target, @.Lbcc_s_target
+ .set bge_s_s7_has_delay_slot, 0
+ .set bge_s_s7_cc, 0xA
+ bge_s_s7_start:
+ bge_s @bge_s_s7_target
+ bge_s_s7_end:
+
+ ; blt_s s7
+ .set blt_s_s7_target, @.Lbcc_s_target
+ .set blt_s_s7_has_delay_slot, 0
+ .set blt_s_s7_cc, 0xB
+ blt_s_s7_start:
+ blt_s @blt_s_s7_target
+ blt_s_s7_end:
+
+ ; ble_s s7
+ .set ble_s_s7_target, @.Lbcc_s_target
+ .set ble_s_s7_has_delay_slot, 0
+ .set ble_s_s7_cc, 0xC
+ ble_s_s7_start:
+ ble_s @ble_s_s7_target
+ ble_s_s7_end:
+
+ ; bhi_s s7
+ .set bhi_s_s7_target, @.Lbcc_s_target
+ .set bhi_s_s7_has_delay_slot, 0
+ .set bhi_s_s7_cc, 0xD
+ bhi_s_s7_start:
+ bhi_s @bhi_s_s7_target
+ bhi_s_s7_end:
+
+ ; bhs_s s7
+ .set bhs_s_s7_target, @.Lbcc_s_target
+ .set bhs_s_s7_has_delay_slot, 0
+ .set bhs_s_s7_cc, 0x6
+ bhs_s_s7_start:
+ bhs_s @bhs_s_s7_target
+ bhs_s_s7_end:
+
+ ; blo_s s7
+ .set blo_s_s7_target, @.Lbcc_s_target
+ .set blo_s_s7_has_delay_slot, 0
+ .set blo_s_s7_cc, 0x5
+ blo_s_s7_start:
+ blo_s @blo_s_s7_target
+ blo_s_s7_end:
+
+ ; bls_s s7
+ .set bls_s_s7_target, @.Lbcc_s_target
+ .set bls_s_s7_has_delay_slot, 0
+ .set bls_s_s7_cc, 0xE
+ bls_s_s7_start:
+ bls_s @bls_s_s7_target
+ bls_s_s7_end:
+#endif /* TEST_BCC */
+
+#ifdef TEST_BI
+ ; bi [c]
+ .set bi_c_target, @bi_c_end + (@r7_value << 2)
+ .set bi_c_has_delay_slot, 0
+ .set bi_c_cc, 0
+ bi_c_start:
+ bi [r7]
+ bi_c_end:
+
+ ; bih [c]
+ .set bih_c_target, @bih_c_end + (@r7_value << 1)
+ .set bih_c_has_delay_slot, 0
+ .set bih_c_cc, 0
+ bih_c_start:
+ bih [r7]
+ bih_c_end:
+#endif /* TEST_BI */
+
+#ifdef TEST_BL
+.Lbl_target:
+ ; bl s25
+ .set bl_s25_target, @.Lbl_target
+ .set bl_s25_has_delay_slot, 0
+ .set bl_s25_cc, 0
+ bl_s25_start:
+ bl @bl_s25_target
+ bl_s25_end:
+
+ ; bl.d s25
+ .set bl_d_s25_target, @.Lbl_target
+ .set bl_d_s25_has_delay_slot, 1
+ .set bl_d_s25_cc, 0
+ bl_d_s25_start:
+ bl.d @bl_d_s25_target
+ bl_d_s25_end:
+ nop_s
+
+ ; bl_s s13
+ .set bl_s_s13_target, @.Lbl_target
+ .set bl_s_s13_has_delay_slot, 0
+ .set bl_s_s13_cc, 0
+ bl_s_s13_start:
+ bl_s @bl_s_s13_target
+ bl_s_s13_end:
+
+ ; blcc s21
+ .set blcc_s21_target, @.Lbl_target
+ .set blcc_s21_has_delay_slot, 0
+ .set blcc_s21_cc, 1
+ blcc_s21_start:
+ bleq @blcc_s21_target
+ blcc_s21_end:
+
+ ; blcc.d s21
+ .set blcc_d_s21_target, @.Lbl_target
+ .set blcc_d_s21_has_delay_slot, 1
+ .set blcc_d_s21_cc, 2
+ blcc_d_s21_start:
+ blnz.d @blcc_d_s21_target
+ blcc_d_s21_end:
+ nop_s
+#endif /* TEST_BL */
+
+#ifdef TEST_BRCC
+.Lbrcc_target:
+ ; breq.nt b,c,s9
+ .set breq_nt_b_c_s9_target, @.Lbrcc_target
+ .set breq_nt_b_c_s9_has_delay_slot, 0
+ .set breq_nt_b_c_s9_cc, 1
+ breq_nt_b_c_s9_start:
+ breq.nt r4,r5,@.Lbrcc_target
+ breq_nt_b_c_s9_end:
+
+ ; breq.d.nt b,c,s9
+ .set breq_d_nt_b_c_s9_target, @.Lbrcc_target
+ .set breq_d_nt_b_c_s9_has_delay_slot, 1
+ .set breq_d_nt_b_c_s9_cc, 1
+ breq_d_nt_b_c_s9_start:
+ breq.d.nt r4,r5,@.Lbrcc_target
+ breq_d_nt_b_c_s9_end:
+ nop_s
+
+ ; breq.t b,c,s9
+ .set breq_t_b_c_s9_target, @.Lbrcc_target
+ .set breq_t_b_c_s9_has_delay_slot, 0
+ .set breq_t_b_c_s9_cc, 1
+ breq_t_b_c_s9_start:
+ breq.t r4,r5,@.Lbrcc_target
+ breq_t_b_c_s9_end:
+
+ ; breq.d.t b,c,s9
+ .set breq_d_t_b_c_s9_target, @.Lbrcc_target
+ .set breq_d_t_b_c_s9_has_delay_slot, 1
+ .set breq_d_t_b_c_s9_cc, 1
+ breq_d_t_b_c_s9_start:
+ breq.d.t r4,r5,@.Lbrcc_target
+ breq_d_t_b_c_s9_end:
+ nop_s
+
+ ; breq.nt b,u6,s9
+ .set breq_nt_b_u6_s9_target, @.Lbrcc_target
+ .set breq_nt_b_u6_s9_has_delay_slot, 0
+ .set breq_nt_b_u6_s9_cc, 1
+ breq_nt_b_u6_s9_start:
+ breq.nt r4,u6_value,@.Lbrcc_target
+ breq_nt_b_u6_s9_end:
+
+ ; breq.d.nt b,u6,s9
+ .set breq_d_nt_b_u6_s9_target, @.Lbrcc_target
+ .set breq_d_nt_b_u6_s9_has_delay_slot, 1
+ .set breq_d_nt_b_u6_s9_cc, 1
+ breq_d_nt_b_u6_s9_start:
+ breq.d.nt r4,u6_value,@.Lbrcc_target
+ breq_d_nt_b_u6_s9_end:
+ nop_s
+
+ ; breq.nt b,u6,s9
+ .set breq_t_b_u6_s9_target, @.Lbrcc_target
+ .set breq_t_b_u6_s9_has_delay_slot, 0
+ .set breq_t_b_u6_s9_cc, 1
+ breq_t_b_u6_s9_start:
+ breq.t r4,u6_value,@.Lbrcc_target
+ breq_t_b_u6_s9_end:
+
+ ; breq.d.nt b,u6,s9
+ .set breq_d_t_b_u6_s9_target, @.Lbrcc_target
+ .set breq_d_t_b_u6_s9_has_delay_slot, 1
+ .set breq_d_t_b_u6_s9_cc, 1
+ breq_d_t_b_u6_s9_start:
+ breq.d.t r4,u6_value,@.Lbrcc_target
+ breq_d_t_b_u6_s9_end:
+ nop_s
+
+ ; breq.nt b,limm,s9
+ .set breq_nt_b_limm_s9_target, @.Lbrcc_target
+ .set breq_nt_b_limm_s9_has_delay_slot, 0
+ .set breq_nt_b_limm_s9_cc, 1
+ breq_nt_b_limm_s9_start:
+ breq.nt r4,limm_value,@.Lbrcc_target
+ breq_nt_b_limm_s9_end:
+
+ ; breq.t b,limm,s9
+ .set breq_t_b_limm_s9_target, @.Lbrcc_target
+ .set breq_t_b_limm_s9_has_delay_slot, 0
+ .set breq_t_b_limm_s9_cc, 1
+ breq_t_b_limm_s9_start:
+ breq.t r4,limm_value,@.Lbrcc_target
+ breq_t_b_limm_s9_end:
+
+ ; breq.nt limm,c,s9
+ .set breq_nt_limm_c_s9_target, @.Lbrcc_target
+ .set breq_nt_limm_c_s9_has_delay_slot, 0
+ .set breq_nt_limm_c_s9_cc, 1
+ breq_nt_limm_c_s9_start:
+ breq.nt limm_value,r4,@.Lbrcc_target
+ breq_nt_limm_c_s9_end:
+
+ ; breq.t limm,c,s9
+ .set breq_t_limm_c_s9_target, @.Lbrcc_target
+ .set breq_t_limm_c_s9_has_delay_slot, 0
+ .set breq_t_limm_c_s9_cc, 1
+ breq_t_limm_c_s9_start:
+ breq.t limm_value,r4,@.Lbrcc_target
+ breq_t_limm_c_s9_end:
+
+ ; breq.nt limm,u6,s9
+ .set breq_nt_limm_u6_s9_target, @.Lbrcc_target
+ .set breq_nt_limm_u6_s9_has_delay_slot, 0
+ .set breq_nt_limm_u6_s9_cc, 1
+ breq_nt_limm_u6_s9_start:
+ breq.nt limm_value,u6_value,@.Lbrcc_target
+ breq_nt_limm_u6_s9_end:
+
+ ; breq.t limm,u6,s9
+ .set breq_t_limm_u6_s9_target, @.Lbrcc_target
+ .set breq_t_limm_u6_s9_has_delay_slot, 0
+ .set breq_t_limm_u6_s9_cc, 1
+ breq_t_limm_u6_s9_start:
+ breq.t limm_value,u6_value,@.Lbrcc_target
+ breq_t_limm_u6_s9_end:
+
+ ; brne_s b,0,s8
+ .set brne_s_b_0_s8_target, @.Lbrcc_target
+ .set brne_s_b_0_s8_has_delay_slot, 0
+ .set brne_s_b_0_s8_cc, 1
+ brne_s_b_0_s8_start:
+ brne r12,0,@.Lbrcc_target
+ brne_s_b_0_s8_end:
+
+ ; breq_s b,0,s8
+ .set breq_s_b_0_s8_target, @.Lbrcc_target
+ .set breq_s_b_0_s8_has_delay_slot, 0
+ .set breq_s_b_0_s8_cc, 1
+ breq_s_b_0_s8_start:
+ breq r12,0,@.Lbrcc_target
+ breq_s_b_0_s8_end:
+#endif /* TEST_BRCC */
+
+#ifdef TEST_JLI
+ ; jli_s u10
+ .set jli_s_u10_target, @jli_target
+ .set jli_s_u10_has_delay_slot, 0
+ .set jli_s_u10_cc, 0
+ jli_s_u10_start:
+ jli_s jli_offset
+ jli_s_u10_end:
+#endif
+
+#ifdef TEST_LEAVE_S
+ ; leave_s
+ .set leave_s_target, @blink_value
+ .set leave_s_has_delay_slot, 0
+ .set leave_s_cc, 0
+ leave_s_start:
+ ; leave_s [r13-gp,fp,blink,pcl]
+ leave_s (14 + 16 + 32 + 64)
+ leave_s_end:
+#endif
+
+#ifdef TEST_LPCC
+ ; lpcc
+ .set lpcc_u7_target, @.Llpcc_end
+ .set lpcc_u7_has_delay_slot, 0
+ .set lpcc_u7_cc, 1
+ lpcc_u7_start:
+ lpeq @lpcc_u7_target
+ lpcc_u7_end:
+ nop
+ nop
+.Llpcc_end:
+#endif
+
+.Lend:
+