Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
0b610de0
Commit
0b610de0
authored
Sep 29, 2014
by
Damien George
Browse files
py: Make macro names in assemblers consistent, and tidy up a bit.
parent
d66e4866
Changes
10
Hide whitespace changes
Inline
Side-by-side
py/asmarm.c
View file @
0b610de0
...
...
@@ -45,9 +45,8 @@ struct _asm_arm_t {
byte
*
code_base
;
byte
dummy_data
[
4
];
uint
max_num_labels
;
int
*
label_offsets
;
int
num_locals
;
mp_uint_t
max_num_labels
;
mp_uint_t
*
label_offsets
;
uint
push_reglist
;
uint
stack_adjust
;
};
...
...
@@ -57,7 +56,7 @@ asm_arm_t *asm_arm_new(uint max_num_labels) {
as
=
m_new0
(
asm_arm_t
,
1
);
as
->
max_num_labels
=
max_num_labels
;
as
->
label_offsets
=
m_new
(
in
t
,
max_num_labels
);
as
->
label_offsets
=
m_new
(
mp_uint_
t
,
max_num_labels
);
return
as
;
}
...
...
@@ -66,7 +65,7 @@ void asm_arm_free(asm_arm_t *as, bool free_code) {
if
(
free_code
)
{
MP_PLAT_FREE_EXEC
(
as
->
code_base
,
as
->
code_size
);
}
m_del
(
mp_uint_t
,
as
->
label_offsets
,
as
->
max_num_labels
);
m_del_obj
(
asm_arm_t
,
as
);
}
...
...
@@ -74,7 +73,7 @@ void asm_arm_start_pass(asm_arm_t *as, uint pass) {
as
->
pass
=
pass
;
as
->
code_offset
=
0
;
if
(
pass
==
ASM_ARM_PASS_COMPUTE
)
{
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
in
t
));
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
mp_uint_
t
));
}
}
...
...
@@ -127,7 +126,7 @@ STATIC void emit(asm_arm_t *as, uint op) {
// Insert word into instruction flow, add "ALWAYS" condition code
STATIC
void
emit_al
(
asm_arm_t
*
as
,
uint
op
)
{
emit
(
as
,
op
|
ARM_CC_AL
);
emit
(
as
,
op
|
ASM_
ARM_CC_AL
);
}
// Basic instructions without condition code
...
...
@@ -178,7 +177,7 @@ void asm_arm_bkpt(asm_arm_t *as) {
// locals:
// - stored on the stack in ascending order
// - numbered 0 through
as->
num_locals-1
// - numbered 0 through num_locals-1
// - SP points to first local
//
// | SP
...
...
@@ -194,30 +193,36 @@ void asm_arm_entry(asm_arm_t *as, int num_locals) {
}
as
->
stack_adjust
=
0
;
as
->
num_locals
=
num_locals
;
as
->
push_reglist
=
1
<<
REG_R1
|
1
<<
REG_R2
|
1
<<
REG_R3
|
1
<<
REG_R4
|
1
<<
REG_R5
|
1
<<
REG_R6
|
1
<<
REG_R7
|
1
<<
REG_R8
;
as
->
push_reglist
=
1
<<
ASM_ARM_REG_R1
|
1
<<
ASM_ARM_REG_R2
|
1
<<
ASM_ARM_REG_R3
|
1
<<
ASM_ARM_REG_R4
|
1
<<
ASM_ARM_REG_R5
|
1
<<
ASM_ARM_REG_R6
|
1
<<
ASM_ARM_REG_R7
|
1
<<
ASM_ARM_REG_R8
;
// Only adjust the stack if there are more locals than usable registers
if
(
num_locals
>
3
)
{
as
->
stack_adjust
=
num_locals
*
4
;
// Align stack to 8 bytes
if
(
as
->
num_locals
&
1
)
if
(
num_locals
&
1
)
{
as
->
stack_adjust
+=
4
;
}
}
emit_al
(
as
,
asm_arm_op_push
(
as
->
push_reglist
|
1
<<
REG_LR
));
emit_al
(
as
,
asm_arm_op_push
(
as
->
push_reglist
|
1
<<
ASM_ARM_
REG_LR
));
if
(
as
->
stack_adjust
>
0
)
{
emit_al
(
as
,
asm_arm_op_sub_imm
(
REG_SP
,
REG_SP
,
as
->
stack_adjust
));
emit_al
(
as
,
asm_arm_op_sub_imm
(
ASM_ARM_REG_SP
,
ASM_ARM_
REG_SP
,
as
->
stack_adjust
));
}
}
void
asm_arm_exit
(
asm_arm_t
*
as
)
{
if
(
as
->
stack_adjust
>
0
)
{
emit_al
(
as
,
asm_arm_op_add_imm
(
REG_SP
,
REG_SP
,
as
->
stack_adjust
));
emit_al
(
as
,
asm_arm_op_add_imm
(
ASM_ARM_REG_SP
,
ASM_ARM_
REG_SP
,
as
->
stack_adjust
));
}
emit_al
(
as
,
asm_arm_op_pop
(
as
->
push_reglist
|
(
1
<<
REG_PC
)));
emit_al
(
as
,
asm_arm_op_pop
(
as
->
push_reglist
|
(
1
<<
ASM_ARM_
REG_PC
)));
}
void
asm_arm_label_assign
(
asm_arm_t
*
as
,
uint
label
)
{
...
...
@@ -289,8 +294,8 @@ void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn) {
void
asm_arm_less_op
(
asm_arm_t
*
as
,
uint
rd
,
uint
rn
,
uint
rm
)
{
asm_arm_cmp_reg_reg
(
as
,
rn
,
rm
);
// cmp rn, rm
emit
(
as
,
asm_arm_op_mov_imm
(
rd
,
1
)
|
ARM_CC_LT
);
// movlt rd, #1
emit
(
as
,
asm_arm_op_mov_imm
(
rd
,
0
)
|
ARM_CC_GE
);
// movge rd, #0
emit
(
as
,
asm_arm_op_mov_imm
(
rd
,
1
)
|
ASM_
ARM_CC_LT
);
// movlt rd, #1
emit
(
as
,
asm_arm_op_mov_imm
(
rd
,
0
)
|
ASM_
ARM_CC_GE
);
// movge rd, #0
}
void
asm_arm_add_reg
(
asm_arm_t
*
as
,
uint
rd
,
uint
rn
,
uint
rm
)
{
...
...
@@ -300,13 +305,13 @@ void asm_arm_add_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
void
asm_arm_mov_reg_local_addr
(
asm_arm_t
*
as
,
uint
rd
,
int
local_num
)
{
// add rd, sp, #local_num*4
emit_al
(
as
,
asm_arm_op_add_imm
(
rd
,
REG_SP
,
local_num
<<
2
));
emit_al
(
as
,
asm_arm_op_add_imm
(
rd
,
ASM_ARM_
REG_SP
,
local_num
<<
2
));
}
void
asm_arm_bcc_label
(
asm_arm_t
*
as
,
int
cond
,
uint
label
)
{
assert
(
label
<
as
->
max_num_labels
);
in
t
dest
=
as
->
label_offsets
[
label
];
in
t
rel
=
dest
-
as
->
code_offset
;
mp_uint_
t
dest
=
as
->
label_offsets
[
label
];
mp_int_
t
rel
=
dest
-
as
->
code_offset
;
rel
-=
8
;
// account for instruction prefetch, PC is 8 bytes ahead of this instruction
rel
>>=
2
;
// in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted
...
...
@@ -318,21 +323,21 @@ void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) {
}
void
asm_arm_b_label
(
asm_arm_t
*
as
,
uint
label
)
{
asm_arm_bcc_label
(
as
,
ARM_CC_AL
,
label
);
asm_arm_bcc_label
(
as
,
ASM_
ARM_CC_AL
,
label
);
}
void
asm_arm_bl_ind
(
asm_arm_t
*
as
,
void
*
fun_ptr
,
uint
fun_id
,
uint
reg_temp
)
{
// If the table offset fits into the ldr instruction
if
(
fun_id
<
(
0x1000
/
4
))
{
emit_al
(
as
,
asm_arm_op_mov_reg
(
REG_LR
,
REG_PC
));
// mov lr, pc
emit_al
(
as
,
asm_arm_op_mov_reg
(
ASM_ARM_REG_LR
,
ASM_ARM_
REG_PC
));
// mov lr, pc
emit_al
(
as
,
0x597f000
|
(
fun_id
<<
2
));
// ldr pc, [r7, #fun_id*4]
return
;
}
emit_al
(
as
,
0x59f0004
|
(
reg_temp
<<
12
));
// ldr rd, [pc, #4]
// Set lr after fun_ptr
emit_al
(
as
,
asm_arm_op_add_imm
(
REG_LR
,
REG_PC
,
4
));
// add lr, pc, #4
emit_al
(
as
,
asm_arm_op_mov_reg
(
REG_PC
,
reg_temp
));
// mov pc, reg_temp
emit_al
(
as
,
asm_arm_op_add_imm
(
ASM_ARM_REG_LR
,
ASM_ARM_
REG_PC
,
4
));
// add lr, pc, #4
emit_al
(
as
,
asm_arm_op_mov_reg
(
ASM_ARM_
REG_PC
,
reg_temp
));
// mov pc, reg_temp
emit
(
as
,
(
uint
)
fun_ptr
);
}
...
...
py/asmarm.h
View file @
0b610de0
...
...
@@ -28,41 +28,41 @@
#define ASM_ARM_PASS_COMPUTE (1)
#define ASM_ARM_PASS_EMIT (2)
#define REG_R0 (0)
#define REG_R1 (1)
#define REG_R2 (2)
#define REG_R3 (3)
#define REG_R4 (4)
#define REG_R5 (5)
#define REG_R6 (6)
#define REG_R7 (7)
#define REG_R8 (8)
#define REG_R9 (9)
#define REG_R10 (10)
#define REG_R11 (11)
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_SP (REG_R13)
#define REG_LR (REG_R14)
#define REG_PC (REG_R15)
#define
ASM_ARM_
REG_R0 (0)
#define
ASM_ARM_
REG_R1 (1)
#define
ASM_ARM_
REG_R2 (2)
#define
ASM_ARM_
REG_R3 (3)
#define
ASM_ARM_
REG_R4 (4)
#define
ASM_ARM_
REG_R5 (5)
#define
ASM_ARM_
REG_R6 (6)
#define
ASM_ARM_
REG_R7 (7)
#define
ASM_ARM_
REG_R8 (8)
#define
ASM_ARM_
REG_R9 (9)
#define
ASM_ARM_
REG_R10 (10)
#define
ASM_ARM_
REG_R11 (11)
#define
ASM_ARM_
REG_R12 (12)
#define
ASM_ARM_
REG_R13 (13)
#define
ASM_ARM_
REG_R14 (14)
#define
ASM_ARM_
REG_R15 (15)
#define
ASM_ARM_
REG_SP (
ASM_ARM_
REG_R13)
#define
ASM_ARM_
REG_LR (
ASM_ARM_
REG_R14)
#define
ASM_ARM_
REG_PC (
ASM_ARM_
REG_R15)
#define ARM_CC_EQ (0x0 << 28)
#define ARM_CC_NE (0x1 << 28)
#define ARM_CC_CS (0x2 << 28)
#define ARM_CC_CC (0x3 << 28)
#define ARM_CC_MI (0x4 << 28)
#define ARM_CC_PL (0x5 << 28)
#define ARM_CC_VS (0x6 << 28)
#define ARM_CC_VC (0x7 << 28)
#define ARM_CC_HI (0x8 << 28)
#define ARM_CC_LS (0x9 << 28)
#define ARM_CC_GE (0xa << 28)
#define ARM_CC_LT (0xb << 28)
#define ARM_CC_GT (0xc << 28)
#define ARM_CC_LE (0xd << 28)
#define ARM_CC_AL (0xe << 28)
#define
ASM_
ARM_CC_EQ (0x0 << 28)
#define
ASM_
ARM_CC_NE (0x1 << 28)
#define
ASM_
ARM_CC_CS (0x2 << 28)
#define
ASM_
ARM_CC_CC (0x3 << 28)
#define
ASM_
ARM_CC_MI (0x4 << 28)
#define
ASM_
ARM_CC_PL (0x5 << 28)
#define
ASM_
ARM_CC_VS (0x6 << 28)
#define
ASM_
ARM_CC_VC (0x7 << 28)
#define
ASM_
ARM_CC_HI (0x8 << 28)
#define
ASM_
ARM_CC_LS (0x9 << 28)
#define
ASM_
ARM_CC_GE (0xa << 28)
#define
ASM_
ARM_CC_LT (0xb << 28)
#define
ASM_
ARM_CC_GT (0xc << 28)
#define
ASM_
ARM_CC_LE (0xd << 28)
#define
ASM_
ARM_CC_AL (0xe << 28)
typedef
struct
_asm_arm_t
asm_arm_t
;
...
...
py/asmthumb.c
View file @
0b610de0
...
...
@@ -68,18 +68,7 @@ void asm_thumb_free(asm_thumb_t *as, bool free_code) {
if
(
free_code
)
{
MP_PLAT_FREE_EXEC
(
as
->
code_base
,
as
->
code_size
);
}
/*
if (as->label != NULL) {
int i;
for (i = 0; i < as->label->len; ++i)
{
Label *lab = &g_array_index(as->label, Label, i);
if (lab->unresolved != NULL)
g_array_free(lab->unresolved, true);
}
g_array_free(as->label, true);
}
*/
m_del
(
mp_uint_t
,
as
->
label_offsets
,
as
->
max_num_labels
);
m_del_obj
(
asm_thumb_t
,
as
);
}
...
...
@@ -284,23 +273,23 @@ void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) {
#define OP_FORMAT_2(op, rlo_dest, rlo_src, src_b) ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest))
void
asm_thumb_format_2
(
asm_thumb_t
*
as
,
uint
op
,
uint
rlo_dest
,
uint
rlo_src
,
int
src_b
)
{
assert
(
rlo_dest
<
REG_R8
);
assert
(
rlo_src
<
REG_R8
);
assert
(
rlo_dest
<
ASM_THUMB_
REG_R8
);
assert
(
rlo_src
<
ASM_THUMB_
REG_R8
);
asm_thumb_op16
(
as
,
OP_FORMAT_2
(
op
,
rlo_dest
,
rlo_src
,
src_b
));
}
#define OP_FORMAT_3(op, rlo, i8) ((op) | ((rlo) << 8) | (i8))
void
asm_thumb_format_3
(
asm_thumb_t
*
as
,
uint
op
,
uint
rlo
,
int
i8
)
{
assert
(
rlo
<
REG_R8
);
assert
(
rlo
<
ASM_THUMB_
REG_R8
);
asm_thumb_op16
(
as
,
OP_FORMAT_3
(
op
,
rlo
,
i8
));
}
#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))
void
asm_thumb_format_4
(
asm_thumb_t
*
as
,
uint
op
,
uint
rlo_dest
,
uint
rlo_src
)
{
assert
(
rlo_dest
<
REG_R8
);
assert
(
rlo_src
<
REG_R8
);
assert
(
rlo_dest
<
ASM_THUMB_
REG_R8
);
assert
(
rlo_src
<
ASM_THUMB_
REG_R8
);
asm_thumb_op16
(
as
,
OP_FORMAT_4
(
op
,
rlo_dest
,
rlo_src
));
}
...
...
@@ -331,7 +320,7 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
// if loading lo half with movw, the i16 value will be zero extended into the r32 register!
STATIC
void
asm_thumb_mov_reg_i16
(
asm_thumb_t
*
as
,
uint
mov_op
,
uint
reg_dest
,
int
i16_src
)
{
assert
(
reg_dest
<
REG_R15
);
assert
(
reg_dest
<
ASM_THUMB_
REG_R15
);
// mov[wt] reg_dest, #i16_src
asm_thumb_op32
(
as
,
mov_op
|
((
i16_src
>>
1
)
&
0x0400
)
|
((
i16_src
>>
12
)
&
0xf
),
((
i16_src
<<
4
)
&
0x7000
)
|
(
reg_dest
<<
8
)
|
(
i16_src
&
0xff
));
}
...
...
@@ -409,14 +398,14 @@ void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
#define OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset) (0x9800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
void
asm_thumb_mov_local_reg
(
asm_thumb_t
*
as
,
int
local_num
,
uint
rlo_src
)
{
assert
(
rlo_src
<
REG_R8
);
assert
(
rlo_src
<
ASM_THUMB_
REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM_THUMB_PASS_EMIT
||
word_offset
>=
0
);
asm_thumb_op16
(
as
,
OP_STR_TO_SP_OFFSET
(
rlo_src
,
word_offset
));
}
void
asm_thumb_mov_reg_local
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
int
local_num
)
{
assert
(
rlo_dest
<
REG_R8
);
assert
(
rlo_dest
<
ASM_THUMB_
REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM_THUMB_PASS_EMIT
||
word_offset
>=
0
);
asm_thumb_op16
(
as
,
OP_LDR_FROM_SP_OFFSET
(
rlo_dest
,
word_offset
));
...
...
@@ -425,7 +414,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
#define OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset) (0xa800 | ((rlo_dest) << 8) | ((word_offset) & 0x00ff))
void
asm_thumb_mov_reg_local_addr
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
int
local_num
)
{
assert
(
rlo_dest
<
REG_R8
);
assert
(
rlo_dest
<
ASM_THUMB_
REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM_THUMB_PASS_EMIT
||
word_offset
>=
0
);
asm_thumb_op16
(
as
,
OP_ADD_REG_SP_OFFSET
(
rlo_dest
,
word_offset
));
...
...
@@ -439,7 +428,7 @@ void asm_thumb_b_label(asm_thumb_t *as, uint label) {
mp_uint_t
dest
=
get_label_dest
(
as
,
label
);
mp_int_t
rel
=
dest
-
as
->
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
if
(
dest
>
=
0
&&
rel
<=
-
4
)
{
if
(
dest
!
=
-
1
&&
rel
<=
-
4
)
{
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 12 bit relative jump
if
(
SIGNED_FIT12
(
rel
))
{
...
...
@@ -462,7 +451,7 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {
mp_uint_t
dest
=
get_label_dest
(
as
,
label
);
mp_int_t
rel
=
dest
-
as
->
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
if
(
dest
>
=
0
&&
rel
<=
-
4
)
{
if
(
dest
!
=
-
1
&&
rel
<=
-
4
)
{
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 9 bit relative jump
if
(
SIGNED_FIT9
(
rel
))
{
...
...
@@ -482,17 +471,17 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) {
void
asm_thumb_bl_ind
(
asm_thumb_t
*
as
,
void
*
fun_ptr
,
uint
fun_id
,
uint
reg_temp
)
{
/* TODO make this use less bytes
uint rlo_base = REG_R3;
uint rlo_dest = REG_R7;
uint rlo_base =
ASM_THUMB_
REG_R3;
uint rlo_dest =
ASM_THUMB_
REG_R7;
uint word_offset = 4;
asm_thumb_op16(as, 0x0000);
asm_thumb_op16(as, 0x6800 | (word_offset << 6) | (rlo_base << 3) | rlo_dest); // ldr rlo_dest, [rlo_base, #offset]
asm_thumb_op16(as, 0x4780 | (REG_R9 << 3)); // blx reg
asm_thumb_op16(as, 0x4780 | (
ASM_THUMB_
REG_R9 << 3)); // blx reg
*/
if
(
fun_id
<
32
)
{
// load ptr to function from table, indexed by fun_id (must be in range 0-31); 4 bytes
asm_thumb_op16
(
as
,
OP_FORMAT_9_10
(
ASM_THUMB_FORMAT_9_LDR
|
ASM_THUMB_FORMAT_9_WORD_TRANSFER
,
reg_temp
,
REG_R7
,
fun_id
));
asm_thumb_op16
(
as
,
OP_FORMAT_9_10
(
ASM_THUMB_FORMAT_9_LDR
|
ASM_THUMB_FORMAT_9_WORD_TRANSFER
,
reg_temp
,
ASM_THUMB_
REG_R7
,
fun_id
));
asm_thumb_op16
(
as
,
OP_BLX
(
reg_temp
));
}
else
{
// load ptr to function into register using immediate; 6 bytes
...
...
py/asmthumb.h
View file @
0b610de0
...
...
@@ -27,38 +27,38 @@
#define ASM_THUMB_PASS_COMPUTE (1)
#define ASM_THUMB_PASS_EMIT (2)
#define REG_R0 (0)
#define REG_R1 (1)
#define REG_R2 (2)
#define REG_R3 (3)
#define REG_R4 (4)
#define REG_R5 (5)
#define REG_R6 (6)
#define REG_R7 (7)
#define REG_R8 (8)
#define REG_R9 (9)
#define REG_R10 (10)
#define REG_R11 (11)
#define REG_R12 (12)
#define REG_R13 (13)
#define REG_R14 (14)
#define REG_R15 (15)
#define REG_LR (REG_R14)
#define THUMB_CC_EQ (0x0)
#define THUMB_CC_NE (0x1)
#define THUMB_CC_CS (0x2)
#define THUMB_CC_CC (0x3)
#define THUMB_CC_MI (0x4)
#define THUMB_CC_PL (0x5)
#define THUMB_CC_VS (0x6)
#define THUMB_CC_VC (0x7)
#define THUMB_CC_HI (0x8)
#define THUMB_CC_LS (0x9)
#define THUMB_CC_GE (0xa)
#define THUMB_CC_LT (0xb)
#define THUMB_CC_GT (0xc)
#define THUMB_CC_LE (0xd)
#define
ASM_THUMB_
REG_R0 (0)
#define
ASM_THUMB_
REG_R1 (1)
#define
ASM_THUMB_
REG_R2 (2)
#define
ASM_THUMB_
REG_R3 (3)
#define
ASM_THUMB_
REG_R4 (4)
#define
ASM_THUMB_
REG_R5 (5)
#define
ASM_THUMB_
REG_R6 (6)
#define
ASM_THUMB_
REG_R7 (7)
#define
ASM_THUMB_
REG_R8 (8)
#define
ASM_THUMB_
REG_R9 (9)
#define
ASM_THUMB_
REG_R10 (10)
#define
ASM_THUMB_
REG_R11 (11)
#define
ASM_THUMB_
REG_R12 (12)
#define
ASM_THUMB_
REG_R13 (13)
#define
ASM_THUMB_
REG_R14 (14)
#define
ASM_THUMB_
REG_R15 (15)
#define
ASM_THUMB_
REG_LR (REG_R14)
#define
ASM_
THUMB_CC_EQ (0x0)
#define
ASM_
THUMB_CC_NE (0x1)
#define
ASM_
THUMB_CC_CS (0x2)
#define
ASM_
THUMB_CC_CC (0x3)
#define
ASM_
THUMB_CC_MI (0x4)
#define
ASM_
THUMB_CC_PL (0x5)
#define
ASM_
THUMB_CC_VS (0x6)
#define
ASM_
THUMB_CC_VC (0x7)
#define
ASM_
THUMB_CC_HI (0x8)
#define
ASM_
THUMB_CC_LS (0x9)
#define
ASM_
THUMB_CC_GE (0xa)
#define
ASM_
THUMB_CC_LT (0xb)
#define
ASM_
THUMB_CC_GT (0xc)
#define
ASM_
THUMB_CC_LE (0xd)
typedef
struct
_asm_thumb_t
asm_thumb_t
;
...
...
py/asmx64.c
View file @
0b610de0
...
...
@@ -114,17 +114,17 @@ struct _asm_x64_t {
byte
*
code_base
;
byte
dummy_data
[
8
];
uint
max_num_labels
;
in
t
*
label_offsets
;
mp_
uint
_t
max_num_labels
;
mp_uint_
t
*
label_offsets
;
int
num_locals
;
};
asm_x64_t
*
asm_x64_new
(
uint
max_num_labels
)
{
asm_x64_t
*
asm_x64_new
(
mp_
uint
_t
max_num_labels
)
{
asm_x64_t
*
as
;
as
=
m_new0
(
asm_x64_t
,
1
);
as
->
max_num_labels
=
max_num_labels
;
as
->
label_offsets
=
m_new
(
in
t
,
max_num_labels
);
as
->
label_offsets
=
m_new
(
mp_uint_
t
,
max_num_labels
);
return
as
;
}
...
...
@@ -133,18 +133,7 @@ void asm_x64_free(asm_x64_t *as, bool free_code) {
if
(
free_code
)
{
MP_PLAT_FREE_EXEC
(
as
->
code_base
,
as
->
code_size
);
}
/*
if (as->label != NULL) {
int i;
for (i = 0; i < as->label->len; ++i)
{
Label* lab = &g_array_index(as->label, Label, i);
if (lab->unresolved != NULL)
g_array_free(lab->unresolved, true);
}
g_array_free(as->label, true);
}
*/
m_del
(
mp_uint_t
,
as
->
label_offsets
,
as
->
max_num_labels
);
m_del_obj
(
asm_x64_t
,
as
);
}
...
...
@@ -153,7 +142,7 @@ void asm_x64_start_pass(asm_x64_t *as, uint pass) {
as
->
code_offset
=
0
;
if
(
pass
==
ASM_X64_PASS_COMPUTE
)
{
// reset all labels
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
in
t
));
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
mp_uint_
t
));
}
}
...
...
@@ -192,7 +181,7 @@ STATIC byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int num_bytes_to_writ
}
}
uint
asm_x64_get_code_size
(
asm_x64_t
*
as
)
{
mp_
uint
_t
asm_x64_get_code_size
(
asm_x64_t
*
as
)
{
return
as
->
code_size
;
}
...
...
@@ -252,9 +241,9 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
STATIC
void
asm_x64_write_r64_disp
(
asm_x64_t
*
as
,
int
r64
,
int
disp_r64
,
int
disp_offset
)
{
assert
(
disp_r64
<
8
);
assert
(
disp_r64
!=
REG_RSP
);
assert
(
disp_r64
!=
ASM_X64_
REG_RSP
);
if
(
disp_offset
==
0
&&
disp_r64
!=
REG_RBP
)
{
if
(
disp_offset
==
0
&&
disp_r64
!=
ASM_X64_
REG_RBP
)
{
asm_x64_write_byte_1
(
as
,
MODRM_R64
(
r64
)
|
MODRM_RM_DISP0
|
MODRM_RM_R64
(
disp_r64
));
}
else
if
(
SIGNED_FIT8
(
disp_offset
))
{
asm_x64_write_byte_2
(
as
,
MODRM_R64
(
r64
)
|
MODRM_RM_DISP8
|
MODRM_RM_R64
(
disp_r64
),
IMM32_L0
(
disp_offset
));
...
...
@@ -400,23 +389,6 @@ void asm_x64_add_r64_to_r64(asm_x64_t *as, int src_r64, int dest_r64) {
asm_x64_write_byte_3
(
as
,
REX_PREFIX
|
REX_W
,
OPCODE_ADD_R64_TO_RM64
,
MODRM_R64
(
src_r64
)
|
MODRM_RM_REG
|
MODRM_RM_R64
(
dest_r64
));
}
/*
void asm_x64_add_i32_to_r32(asm_x64_t *as, int src_i32, int dest_r32)
{
assert(dest_r32 != REG_RSP); // in this case i think src_i32 must be 64 bits
if (SIGNED_FIT8(src_i32))
{
asm_x64_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r32));
asm_x64_write_byte_1(as, src_i32 & 0xff);
}
else
{
asm_x64_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R64(0) | MODRM_RM_REG | MODRM_RM_R64(dest_r32));
asm_x64_write_word32(as, src_i32);
}
}
*/
/*
void asm_x64_sub_r32_from_r32(asm_x64_t *as, int src_r32, int dest_r32) {
// defaults to 32 bit operation
...
...
@@ -495,8 +467,8 @@ void asm_x64_cmp_i32_with_r32(asm_x64_t *as, int src_i32, int src_r32) {
void
asm_x64_test_r8_with_r8
(
asm_x64_t
*
as
,
int
src_r64_a
,
int
src_r64_b
)
{
// TODO implement for other registers
assert
(
src_r64_a
==
REG_RAX
);
assert
(
src_r64_b
==
REG_RAX
);
assert
(
src_r64_a
==
ASM_X64_
REG_RAX
);
assert
(
src_r64_b
==
ASM_X64_
REG_RAX
);
asm_x64_write_byte_2
(
as
,
OPCODE_TEST_R8_WITH_RM8
,
MODRM_R64
(
src_r64_a
)
|
MODRM_RM_REG
|
MODRM_RM_R64
(
src_r64_b
));
}
...
...
@@ -513,20 +485,20 @@ void asm_x64_label_assign(asm_x64_t *as, int label) {
as
->
label_offsets
[
label
]
=
as
->
code_offset
;
}
else
{
// ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
//printf("l%d: (at %d=%ld)\n", label, as->label_offsets[label], as->code_offset);
//printf("l%d: (at %
l
d=%ld)\n", label, as->label_offsets[label], as->code_offset);
assert
(
as
->
label_offsets
[
label
]
==
as
->
code_offset
);
}
}
STATIC
in
t
get_label_dest
(
asm_x64_t
*
as
,
int
label
)
{
STATIC
mp_uint_
t
get_label_dest
(
asm_x64_t
*
as
,
int
label
)
{
assert
(
label
<
as
->
max_num_labels
);
return
as
->
label_offsets
[
label
];
}
void
asm_x64_jmp_label
(
asm_x64_t
*
as
,
int
label
)
{
in
t
dest
=
get_label_dest
(
as
,
label
);
in
t
rel
=
dest
-
as
->
code_offset
;
if
(
dest
>
=
0
&&
rel
<
0
)
{
mp_uint_
t
dest
=
get_label_dest
(
as
,
label
);
mp_int_
t
rel
=
dest
-
as
->
code_offset
;
if
(
dest
!
=
-
1
&&
rel
<
0
)
{
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 8 bit relative jump
rel
-=
2
;
...
...
@@ -546,9 +518,9 @@ void asm_x64_jmp_label(asm_x64_t *as, int label) {
}
void
asm_x64_jcc_label
(
asm_x64_t
*
as
,
int
jcc_type
,
int
label
)
{
in
t
dest
=
get_label_dest
(
as
,
label
);
in
t
rel
=
dest
-
as
->
code_offset
;
if
(
dest
>
=
0
&&
rel
<
0
)
{
mp_uint_
t
dest
=
get_label_dest
(
as
,
label
);
mp_int_
t
rel
=
dest
-
as
->
code_offset
;
if
(
dest
!
=
-
1
&&
rel
<
0
)
{
// is a backwards jump, so we know the size of the jump on the first pass
// calculate rel assuming 8 bit relative jump
rel
-=
2
;
...
...
@@ -568,23 +540,23 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, int label) {
}
void
asm_x64_entry
(
asm_x64_t
*
as
,
int
num_locals
)
{
asm_x64_push_r64
(
as
,
REG_RBP
);
asm_x64_mov_r64_to_r64
(
as
,
REG_RSP
,
REG_RBP
);
asm_x64_push_r64
(
as
,
ASM_X64_
REG_RBP
);
asm_x64_mov_r64_to_r64
(
as
,
ASM_X64_
REG_RSP
,
ASM_X64_
REG_RBP
);
if
(
num_locals
<
0
)
{
num_locals
=
0
;
}
num_locals
|=
1
;
// make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_i32_from_r64
(
as
,
num_locals
*
WORD_SIZE
,
REG_RSP
);
asm_x64_push_r64
(
as
,
REG_RBX
);
asm_x64_push_r64
(
as
,
REG_R12
);
asm_x64_push_r64
(
as
,
REG_R13
);
asm_x64_sub_i32_from_r64
(
as
,
num_locals
*
WORD_SIZE
,
ASM_X64_
REG_RSP
);
asm_x64_push_r64
(
as
,
ASM_X64_
REG_RBX
);
asm_x64_push_r64
(
as
,
ASM_X64_
REG_R12
);
asm_x64_push_r64
(
as
,
ASM_X64_
REG_R13
);
as
->
num_locals
=
num_locals
;
}
void
asm_x64_exit
(
asm_x64_t
*
as
)
{
asm_x64_pop_r64
(
as
,
REG_R13
);
asm_x64_pop_r64
(
as
,
REG_R12
);
asm_x64_pop_r64
(
as
,
REG_RBX
);
asm_x64_pop_r64
(
as
,
ASM_X64_
REG_R13
);
asm_x64_pop_r64
(
as
,
ASM_X64_
REG_R12
);
asm_x64_pop_r64
(
as
,
ASM_X64_
REG_RBX
);
asm_x64_write_byte_1
(
as
,
OPCODE_LEAVE
);
asm_x64_ret
(
as
);
}
...
...
@@ -605,30 +577,30 @@ STATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {
}
void
asm_x64_mov_local_to_r64
(
asm_x64_t
*
as
,
int
src_local_num
,
int
dest_r64
)
{
asm_x64_mov_disp_to_r64
(
as
,
REG_RBP
,
asm_x64_local_offset_from_ebp
(
as
,
src_local_num
),
dest_r64
);
asm_x64_mov_disp_to_r64
(
as
,
ASM_X64_
REG_RBP
,
asm_x64_local_offset_from_ebp
(
as
,
src_local_num
),
dest_r64
);
}
void
asm_x64_mov_r64_to_local
(
asm_x64_t
*
as
,
int
src_r64
,
int
dest_local_num
)
{
asm_x64_mov_r64_to_disp
(
as
,
src_r64
,
REG_RBP
,
asm_x64_local_offset_from_ebp
(
as
,
dest_local_num
));
asm_x64_mov_r64_to_disp
(
as
,
src_r64
,
ASM_X64_
REG_RBP
,
asm_x64_local_offset_from_ebp
(
as
,
dest_local_num
));
}
void
asm_x64_mov_local_addr_to_r64
(
asm_x64_t
*
as
,
int
local_num
,
int
dest_r64
)
{
int
offset
=
asm_x64_local_offset_from_ebp
(
as
,
local_num
);
if
(
offset
==
0
)
{
asm_x64_mov_r64_to_r64
(
as
,
REG_RBP
,
dest_r64
);
asm_x64_mov_r64_to_r64
(
as
,
ASM_X64_
REG_RBP
,
dest_r64
);
}
else
{
asm_x64_lea_disp_to_r64
(
as
,
REG_RBP
,
offset
,
dest_r64
);
asm_x64_lea_disp_to_r64
(
as
,
ASM_X64_
REG_RBP
,
offset
,
dest_r64
);
}
}
/*
void asm_x64_push_local(asm_x64_t *as, int local_num) {
asm_x64_push_disp(as, REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
asm_x64_push_disp(as,
ASM_X64_
REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
}
void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64)
{
asm_x64_mov_r64_to_r64(as, REG_RBP, temp_r64);
asm_x64_mov_r64_to_r64(as,
ASM_X64_
REG_RBP, temp_r64);