Add b_n opcode to inline thumb asm.
This commit is contained in:
parent
b14de21fc8
commit
03d4124320
@ -288,6 +288,19 @@ void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) {
|
|||||||
asm_thumb_write_op16(as, OP_CMP_RLO_I8(rlo, i8));
|
asm_thumb_write_op16(as, OP_CMP_RLO_I8(rlo, i8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))
|
||||||
|
|
||||||
|
void asm_thumb_b_n(asm_thumb_t *as, int label) {
|
||||||
|
int dest = get_label_dest(as, label);
|
||||||
|
int rel = dest - as->code_offset;
|
||||||
|
rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction
|
||||||
|
if (SIGNED_FIT12(rel)) {
|
||||||
|
asm_thumb_write_op16(as, OP_B_N(rel));
|
||||||
|
} else {
|
||||||
|
printf("asm_thumb_b_n: branch does not fit in 12 bits\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define OP_BEQ_N(byte_offset) (0xd000 | (((byte_offset) >> 1) & 0x00ff))
|
#define OP_BEQ_N(byte_offset) (0xd000 | (((byte_offset) >> 1) & 0x00ff))
|
||||||
#define OP_BNE_N(byte_offset) (0xd100 | (((byte_offset) >> 1) & 0x00ff))
|
#define OP_BNE_N(byte_offset) (0xd100 | (((byte_offset) >> 1) & 0x00ff))
|
||||||
#define OP_BCS_N(byte_offset) (0xd200 | (((byte_offset) >> 1) & 0x00ff))
|
#define OP_BCS_N(byte_offset) (0xd200 | (((byte_offset) >> 1) & 0x00ff))
|
||||||
@ -371,7 +384,6 @@ void asm_thumb_ite_ge(asm_thumb_t *as) {
|
|||||||
asm_thumb_write_op16(as, 0xbfac);
|
asm_thumb_write_op16(as, 0xbfac);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OP_B(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))
|
|
||||||
// this could be wrong, because it should have a range of +/- 16MiB...
|
// this could be wrong, because it should have a range of +/- 16MiB...
|
||||||
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
|
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
|
||||||
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
|
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
|
||||||
@ -384,7 +396,7 @@ void asm_thumb_b_label(asm_thumb_t *as, int label) {
|
|||||||
// is a backwards jump, so we know the size of the jump on the first pass
|
// is a backwards jump, so we know the size of the jump on the first pass
|
||||||
// calculate rel assuming 12 bit relative jump
|
// calculate rel assuming 12 bit relative jump
|
||||||
if (SIGNED_FIT12(rel)) {
|
if (SIGNED_FIT12(rel)) {
|
||||||
asm_thumb_write_op16(as, OP_B(rel));
|
asm_thumb_write_op16(as, OP_B_N(rel));
|
||||||
} else {
|
} else {
|
||||||
goto large_jump;
|
goto large_jump;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src);
|
|||||||
void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);
|
void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);
|
||||||
void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src);
|
void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src);
|
||||||
void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8);
|
void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8);
|
||||||
|
void asm_thumb_b_n(asm_thumb_t *as, int label);
|
||||||
void asm_thumb_bgt_n(asm_thumb_t *as, int label);
|
void asm_thumb_bgt_n(asm_thumb_t *as, int label);
|
||||||
|
|
||||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32_src); // convenience
|
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32_src); // convenience
|
||||||
|
@ -52,7 +52,7 @@ static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
|
|||||||
|
|
||||||
static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params) {
|
static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params) {
|
||||||
if (n_params > 4) {
|
if (n_params > 4) {
|
||||||
printf("SyntaxError: can only have up to 3 parameters to inline assembler\n");
|
printf("SyntaxError: can only have up to 4 parameters to inline thumb assembly\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < n_params; i++) {
|
for (int i = 0; i < n_params; i++) {
|
||||||
@ -62,7 +62,7 @@ static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params,
|
|||||||
}
|
}
|
||||||
const char *p = qstr_str(PY_PARSE_NODE_LEAF_ARG(pn_params[i]));
|
const char *p = qstr_str(PY_PARSE_NODE_LEAF_ARG(pn_params[i]));
|
||||||
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
|
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
|
||||||
printf("SyntaxError: parameter %d to inline assembler must be r%d\n", i, i);
|
printf("SyntaxError: parameter %d to inline assembler must be r%d\n", i + 1, i);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,6 +128,9 @@ static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_a
|
|||||||
|
|
||||||
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args) {
|
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args) {
|
||||||
// TODO perhaps make two tables:
|
// TODO perhaps make two tables:
|
||||||
|
// one_args =
|
||||||
|
// "b", LAB, asm_thumb_b_n,
|
||||||
|
// "bgt", LAB, asm_thumb_bgt_n,
|
||||||
// two_args =
|
// two_args =
|
||||||
// "movs", RLO, I8, asm_thumb_movs_reg_i8
|
// "movs", RLO, I8, asm_thumb_movs_reg_i8
|
||||||
// "movw", REG, REG, asm_thumb_movw_reg_i16
|
// "movw", REG, REG, asm_thumb_movw_reg_i16
|
||||||
@ -135,7 +138,14 @@ static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, p
|
|||||||
// "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
|
// "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
|
||||||
|
|
||||||
// 1 arg
|
// 1 arg
|
||||||
if (strcmp(qstr_str(op), "bgt") == 0) {
|
if (strcmp(qstr_str(op), "b") == 0) {
|
||||||
|
if (!check_n_arg(op, n_args, 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int label_num = get_arg_label(emit, op, pn_args, 0);
|
||||||
|
// TODO check that this succeeded, ie branch was within range
|
||||||
|
asm_thumb_b_n(emit->as, label_num);
|
||||||
|
} else if (strcmp(qstr_str(op), "bgt") == 0) {
|
||||||
if (!check_n_arg(op, n_args, 1)) {
|
if (!check_n_arg(op, n_args, 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user