mirror of
https://github.com/pound-emu/ballistic.git
synced 2026-06-17 04:16:48 -07:00
assembler: emit B instruction
Signed-off-by: Ronald Caesar <github43132@proton.me>
This commit is contained in:
@@ -93,6 +93,23 @@ extern "C"
|
||||
uint16_t imm12,
|
||||
uint8_t shift);
|
||||
|
||||
/// Emits a `B` (Branch) instruction.
|
||||
///
|
||||
/// Branches unconditionally to a PC-relative offset.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `offset` will be truncated if it exceeds 26 bits.
|
||||
/// * Does not emit if `assembler->status` != [`BAL_SUCCESS`]
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Modifies `assembler->status` to the following if an error occurs:
|
||||
///
|
||||
/// * [`BAL_ERROR_INSTRUCTION_OVERFLOW`] if `assembler->offset >= assembler->capacity`.
|
||||
/// * [`BAL_ERROR_INVALID_ARGUMENT`] if function arguments are invalid.
|
||||
void bal_emit_b(bal_assembler_t *assembler, int32_t offset);
|
||||
|
||||
/// Emit a `SUB` (Immediate) instruction.
|
||||
///
|
||||
/// Subtracts a 12 bit immediate value `imm12` with the optional left shift `sh` from register
|
||||
|
||||
@@ -104,6 +104,63 @@ bal_emit_add_immediate(bal_assembler_t *assembler,
|
||||
assembler->buffer[assembler->offset++] = instruction;
|
||||
}
|
||||
|
||||
void
|
||||
bal_emit_b(bal_assembler_t *assembler, const int32_t offset)
|
||||
{
|
||||
if (BAL_UNLIKELY(NULL == assembler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (BAL_UNLIKELY(NULL == assembler->buffer))
|
||||
{
|
||||
BAL_LOG_ERROR(&assembler->logger, "Aborting function: assembler->buffer is NULL");
|
||||
assembler->status = BAL_ERROR_INVALID_ARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
const bool can_emit_return_value = can_emit(assembler);
|
||||
|
||||
if (false == can_emit_return_value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (assembler->status != BAL_SUCCESS)
|
||||
{
|
||||
BAL_LOG_ERROR(&assembler->logger, "Aborting function: assembler->status != BAL_SUCCESS");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t hard_coded_bits = 0x14000000;
|
||||
|
||||
// WARNING: Cast to uint32_t safely applies bitwise masking to negative values.
|
||||
const uint32_t imm26 = (uint32_t)(offset / 4) & 0x03FFFFFF;
|
||||
uint32_t instruction = 0;
|
||||
|
||||
if (0 == imm26)
|
||||
{
|
||||
instruction = hard_coded_bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction = hard_coded_bits / imm26;
|
||||
}
|
||||
|
||||
const char *mnemonic = "B";
|
||||
BAL_LOG_TRACE(&assembler->logger,
|
||||
"[+0x%04zx] %08x %s #%d",
|
||||
assembler->offset * sizeof(uint32_t),
|
||||
instruction,
|
||||
mnemonic,
|
||||
offset);
|
||||
|
||||
// WARNING: Prevents unsued local variable compiler warning.
|
||||
(void)mnemonic;
|
||||
|
||||
assembler->buffer[assembler->offset++] = instruction;
|
||||
}
|
||||
|
||||
void
|
||||
bal_emit_sub_immediate(bal_assembler_t *assembler,
|
||||
const bal_register_index_t rd,
|
||||
|
||||
Reference in New Issue
Block a user