Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
61259958
Commit
61259958
authored
Nov 28, 2016
by
Damien George
Browse files
py: Factor out common code from assemblers into asmbase.[ch].
All assemblers should "derive" from mp_asm_base_t.
parent
21e1703d
Changes
13
Hide whitespace changes
Inline
Side-by-side
py/asmarm.c
View file @
61259958
...
...
@@ -38,50 +38,6 @@
#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000)
struct
_asm_arm_t
{
uint
pass
;
mp_uint_t
code_offset
;
mp_uint_t
code_size
;
byte
*
code_base
;
byte
dummy_data
[
4
];
mp_uint_t
max_num_labels
;
mp_uint_t
*
label_offsets
;
uint
push_reglist
;
uint
stack_adjust
;
};
asm_arm_t
*
asm_arm_new
(
uint
max_num_labels
)
{
asm_arm_t
*
as
;
as
=
m_new0
(
asm_arm_t
,
1
);
as
->
max_num_labels
=
max_num_labels
;
as
->
label_offsets
=
m_new
(
mp_uint_t
,
max_num_labels
);
return
as
;
}
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
);
}
void
asm_arm_start_pass
(
asm_arm_t
*
as
,
uint
pass
)
{
if
(
pass
==
ASM_ARM_PASS_COMPUTE
)
{
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
mp_uint_t
));
}
else
if
(
pass
==
ASM_ARM_PASS_EMIT
)
{
MP_PLAT_ALLOC_EXEC
(
as
->
code_offset
,
(
void
**
)
&
as
->
code_base
,
&
as
->
code_size
);
if
(
as
->
code_base
==
NULL
)
{
assert
(
0
);
}
}
as
->
pass
=
pass
;
as
->
code_offset
=
0
;
}
void
asm_arm_end_pass
(
asm_arm_t
*
as
)
{
if
(
as
->
pass
==
ASM_ARM_PASS_EMIT
)
{
#ifdef __arm__
...
...
@@ -97,32 +53,6 @@ void asm_arm_end_pass(asm_arm_t *as) {
}
}
// all functions must go through this one to emit bytes
// if as->pass < ASM_ARM_PASS_EMIT, then this function only returns a buffer of 4 bytes length
STATIC
byte
*
asm_arm_get_cur_to_write_bytes
(
asm_arm_t
*
as
,
int
num_bytes_to_write
)
{
if
(
as
->
pass
<
ASM_ARM_PASS_EMIT
)
{
as
->
code_offset
+=
num_bytes_to_write
;
return
as
->
dummy_data
;
}
else
{
assert
(
as
->
code_offset
+
num_bytes_to_write
<=
as
->
code_size
);
byte
*
c
=
as
->
code_base
+
as
->
code_offset
;
as
->
code_offset
+=
num_bytes_to_write
;
return
c
;
}
}
uint
asm_arm_get_code_pos
(
asm_arm_t
*
as
)
{
return
as
->
code_offset
;
}
uint
asm_arm_get_code_size
(
asm_arm_t
*
as
)
{
return
as
->
code_size
;
}
void
*
asm_arm_get_code
(
asm_arm_t
*
as
)
{
return
as
->
code_base
;
}
// Insert word into instruction flow
STATIC
void
emit
(
asm_arm_t
*
as
,
uint
op
)
{
*
(
uint
*
)
asm_arm_get_cur_to_write_bytes
(
as
,
4
)
=
op
;
...
...
@@ -263,35 +193,6 @@ void asm_arm_pop(asm_arm_t *as, uint reglist) {
emit_al
(
as
,
asm_arm_op_pop
(
reglist
));
}
void
asm_arm_label_assign
(
asm_arm_t
*
as
,
uint
label
)
{
assert
(
label
<
as
->
max_num_labels
);
if
(
as
->
pass
<
ASM_ARM_PASS_EMIT
)
{
// assign label offset
assert
(
as
->
label_offsets
[
label
]
==
-
1
);
as
->
label_offsets
[
label
]
=
as
->
code_offset
;
}
else
{
// ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
assert
(
as
->
label_offsets
[
label
]
==
as
->
code_offset
);
}
}
void
asm_arm_align
(
asm_arm_t
*
as
,
uint
align
)
{
// TODO fill unused data with NOPs?
as
->
code_offset
=
(
as
->
code_offset
+
align
-
1
)
&
(
~
(
align
-
1
));
}
void
asm_arm_data
(
asm_arm_t
*
as
,
uint
bytesize
,
uint
val
)
{
byte
*
c
=
asm_arm_get_cur_to_write_bytes
(
as
,
bytesize
);
// only write to the buffer in the emit pass (otherwise we overflow dummy_data)
if
(
as
->
pass
==
ASM_ARM_PASS_EMIT
)
{
// little endian
for
(
uint
i
=
0
;
i
<
bytesize
;
i
++
)
{
*
c
++
=
val
;
val
>>=
8
;
}
}
}
void
asm_arm_mov_reg_reg
(
asm_arm_t
*
as
,
uint
reg_dest
,
uint
reg_src
)
{
emit_al
(
as
,
asm_arm_op_mov_reg
(
reg_dest
,
reg_src
));
}
...
...
py/asmarm.h
View file @
61259958
...
...
@@ -28,9 +28,7 @@
#define __MICROPY_INCLUDED_PY_ASMARM_H__
#include
"py/misc.h"
#define ASM_ARM_PASS_COMPUTE (1)
#define ASM_ARM_PASS_EMIT (2)
#include
"py/asmbase.h"
#define ASM_ARM_REG_R0 (0)
#define ASM_ARM_REG_R1 (1)
...
...
@@ -68,22 +66,16 @@
#define ASM_ARM_CC_LE (0xd << 28)
#define ASM_ARM_CC_AL (0xe << 28)
typedef
struct
_asm_arm_t
asm_arm_t
;
typedef
struct
_asm_arm_t
{
mp_asm_base_t
base
;
uint
push_reglist
;
uint
stack_adjust
;
}
asm_arm_t
;
asm_arm_t
*
asm_arm_new
(
uint
max_num_labels
);
void
asm_arm_free
(
asm_arm_t
*
as
,
bool
free_code
);
void
asm_arm_start_pass
(
asm_arm_t
*
as
,
uint
pass
);
void
asm_arm_end_pass
(
asm_arm_t
*
as
);
uint
asm_arm_get_code_pos
(
asm_arm_t
*
as
);
uint
asm_arm_get_code_size
(
asm_arm_t
*
as
);
void
*
asm_arm_get_code
(
asm_arm_t
*
as
);
void
asm_arm_entry
(
asm_arm_t
*
as
,
int
num_locals
);
void
asm_arm_exit
(
asm_arm_t
*
as
);
void
asm_arm_label_assign
(
asm_arm_t
*
as
,
uint
label
);
void
asm_arm_align
(
asm_arm_t
*
as
,
uint
align
);
void
asm_arm_data
(
asm_arm_t
*
as
,
uint
bytesize
,
uint
val
);
void
asm_arm_bkpt
(
asm_arm_t
*
as
);
...
...
py/asmbase.c
0 → 100644
View file @
61259958
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include
<assert.h>
#include
<string.h>
#include
"py/obj.h"
#include
"py/misc.h"
#include
"py/asmbase.h"
#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
void
mp_asm_base_init
(
mp_asm_base_t
*
as
,
size_t
max_num_labels
)
{
as
->
max_num_labels
=
max_num_labels
;
as
->
label_offsets
=
m_new
(
size_t
,
max_num_labels
);
}
void
mp_asm_base_deinit
(
mp_asm_base_t
*
as
,
bool
free_code
)
{
if
(
free_code
)
{
MP_PLAT_FREE_EXEC
(
as
->
code_base
,
as
->
code_size
);
}
m_del
(
size_t
,
as
->
label_offsets
,
as
->
max_num_labels
);
}
void
mp_asm_base_start_pass
(
mp_asm_base_t
*
as
,
int
pass
)
{
if
(
pass
==
MP_ASM_PASS_COMPUTE
)
{
// reset all labels
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
size_t
));
}
else
if
(
pass
==
MP_ASM_PASS_EMIT
)
{
// allocating executable RAM is platform specific
MP_PLAT_ALLOC_EXEC
(
as
->
code_offset
,
(
void
**
)
&
as
->
code_base
,
&
as
->
code_size
);
assert
(
as
->
code_base
!=
NULL
);
}
as
->
pass
=
pass
;
as
->
code_offset
=
0
;
}
// all functions must go through this one to emit bytes
// if as->pass < MP_ASM_PASS_EMIT, then this function returns dummy_data
uint8_t
*
mp_asm_base_get_cur_to_write_bytes
(
mp_asm_base_t
*
as
,
size_t
num_bytes_to_write
)
{
if
(
as
->
pass
<
MP_ASM_PASS_EMIT
)
{
as
->
code_offset
+=
num_bytes_to_write
;
return
as
->
dummy_data
;
}
else
{
assert
(
as
->
code_offset
+
num_bytes_to_write
<=
as
->
code_size
);
uint8_t
*
c
=
as
->
code_base
+
as
->
code_offset
;
as
->
code_offset
+=
num_bytes_to_write
;
return
c
;
}
}
void
mp_asm_base_label_assign
(
mp_asm_base_t
*
as
,
size_t
label
)
{
assert
(
label
<
as
->
max_num_labels
);
if
(
as
->
pass
<
MP_ASM_PASS_EMIT
)
{
// assign label offset
assert
(
as
->
label_offsets
[
label
]
==
(
size_t
)
-
1
);
as
->
label_offsets
[
label
]
=
as
->
code_offset
;
}
else
{
// ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT
assert
(
as
->
label_offsets
[
label
]
==
as
->
code_offset
);
}
}
// align must be a multiple of 2
void
mp_asm_base_align
(
mp_asm_base_t
*
as
,
unsigned
int
align
)
{
as
->
code_offset
=
(
as
->
code_offset
+
align
-
1
)
&
(
~
(
align
-
1
));
}
// this function assumes a little endian machine
void
mp_asm_base_data
(
mp_asm_base_t
*
as
,
unsigned
int
bytesize
,
uintptr_t
val
)
{
uint8_t
*
c
=
mp_asm_base_get_cur_to_write_bytes
(
as
,
bytesize
);
// only write to the buffer in the emit pass (otherwise we may overflow dummy_data)
if
(
as
->
pass
==
MP_ASM_PASS_EMIT
)
{
for
(
unsigned
int
i
=
0
;
i
<
bytesize
;
i
++
)
{
*
c
++
=
val
;
val
>>=
8
;
}
}
}
#endif // MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
py/asmbase.h
0 → 100644
View file @
61259958
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_PY_ASMBASE_H
#define MICROPY_INCLUDED_PY_ASMBASE_H
#include
<stdint.h>
#include
<stdbool.h>
#define MP_ASM_PASS_COMPUTE (1)
#define MP_ASM_PASS_EMIT (2)
typedef
struct
_mp_asm_base_t
{
int
pass
;
size_t
code_offset
;
size_t
code_size
;
uint8_t
*
code_base
;
size_t
max_num_labels
;
size_t
*
label_offsets
;
// must be last in struct
uint8_t
dummy_data
[
4
];
}
mp_asm_base_t
;
void
mp_asm_base_init
(
mp_asm_base_t
*
as
,
size_t
max_num_labels
);
void
mp_asm_base_deinit
(
mp_asm_base_t
*
as
,
bool
free_code
);
void
mp_asm_base_start_pass
(
mp_asm_base_t
*
as
,
int
pass
);
uint8_t
*
mp_asm_base_get_cur_to_write_bytes
(
mp_asm_base_t
*
as
,
size_t
num_bytes_to_write
);
void
mp_asm_base_label_assign
(
mp_asm_base_t
*
as
,
size_t
label
);
void
mp_asm_base_align
(
mp_asm_base_t
*
as
,
unsigned
int
align
);
void
mp_asm_base_data
(
mp_asm_base_t
*
as
,
unsigned
int
bytesize
,
uintptr_t
val
);
static
inline
size_t
mp_asm_base_get_code_pos
(
mp_asm_base_t
*
as
)
{
return
as
->
code_offset
;
}
static
inline
size_t
mp_asm_base_get_code_size
(
mp_asm_base_t
*
as
)
{
return
as
->
code_size
;
}
static
inline
void
*
mp_asm_base_get_code
(
mp_asm_base_t
*
as
)
{
return
as
->
code_base
;
}
#endif // MICROPY_INCLUDED_PY_ASMBASE_H
py/asmthumb.c
View file @
61259958
...
...
@@ -42,49 +42,8 @@
#define SIGNED_FIT12(x) (((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)
#define SIGNED_FIT23(x) (((x) & 0xffc00000) == 0) || (((x) & 0xffc00000) == 0xffc00000)
struct
_asm_thumb_t
{
mp_uint_t
pass
;
mp_uint_t
code_offset
;
mp_uint_t
code_size
;
byte
*
code_base
;
byte
dummy_data
[
4
];
mp_uint_t
max_num_labels
;
mp_uint_t
*
label_offsets
;
mp_uint_t
push_reglist
;
mp_uint_t
stack_adjust
;
};
asm_thumb_t
*
asm_thumb_new
(
uint
max_num_labels
)
{
asm_thumb_t
*
as
;
as
=
m_new0
(
asm_thumb_t
,
1
);
as
->
max_num_labels
=
max_num_labels
;
as
->
label_offsets
=
m_new
(
mp_uint_t
,
max_num_labels
);
return
as
;
}
void
asm_thumb_free
(
asm_thumb_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_thumb_t
,
as
);
}
void
asm_thumb_start_pass
(
asm_thumb_t
*
as
,
uint
pass
)
{
if
(
pass
==
ASM_THUMB_PASS_COMPUTE
)
{
memset
(
as
->
label_offsets
,
-
1
,
as
->
max_num_labels
*
sizeof
(
mp_uint_t
));
}
else
if
(
pass
==
ASM_THUMB_PASS_EMIT
)
{
MP_PLAT_ALLOC_EXEC
(
as
->
code_offset
,
(
void
**
)
&
as
->
code_base
,
&
as
->
code_size
);
if
(
as
->
code_base
==
NULL
)
{
assert
(
0
);
}
//printf("code_size: %u\n", as->code_size);
}
as
->
pass
=
pass
;
as
->
code_offset
=
0
;
static
inline
byte
*
asm_thumb_get_cur_to_write_bytes
(
asm_thumb_t
*
as
,
int
n
)
{
return
mp_asm_base_get_cur_to_write_bytes
(
&
as
->
base
,
n
);
}
void
asm_thumb_end_pass
(
asm_thumb_t
*
as
)
{
...
...
@@ -92,7 +51,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
// could check labels are resolved...
#if defined(MCU_SERIES_F7)
if
(
as
->
pass
==
ASM
_THUMB
_PASS_EMIT
)
{
if
(
as
->
base
.
pass
==
MP_
ASM_PASS_EMIT
)
{
// flush D-cache, so the code emited is stored in memory
SCB_CleanDCache_by_Addr
((
uint32_t
*
)
as
->
code_base
,
as
->
code_size
);
// invalidate I-cache
...
...
@@ -101,33 +60,6 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
#endif
}
// all functions must go through this one to emit bytes
// if as->pass < ASM_THUMB_PASS_EMIT, then this function only returns a buffer of 4 bytes length
STATIC
byte
*
asm_thumb_get_cur_to_write_bytes
(
asm_thumb_t
*
as
,
int
num_bytes_to_write
)
{
//printf("emit %d\n", num_bytes_to_write);
if
(
as
->
pass
<
ASM_THUMB_PASS_EMIT
)
{
as
->
code_offset
+=
num_bytes_to_write
;
return
as
->
dummy_data
;
}
else
{
assert
(
as
->
code_offset
+
num_bytes_to_write
<=
as
->
code_size
);
byte
*
c
=
as
->
code_base
+
as
->
code_offset
;
as
->
code_offset
+=
num_bytes_to_write
;
return
c
;
}
}
uint
asm_thumb_get_code_pos
(
asm_thumb_t
*
as
)
{
return
as
->
code_offset
;
}
uint
asm_thumb_get_code_size
(
asm_thumb_t
*
as
)
{
return
as
->
code_size
;
}
void
*
asm_thumb_get_code
(
asm_thumb_t
*
as
)
{
return
as
->
code_base
;
}
/*
STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) {
byte *c = asm_thumb_get_cur_to_write_bytes(as, 1);
...
...
@@ -223,39 +155,9 @@ void asm_thumb_exit(asm_thumb_t *as) {
asm_thumb_op16
(
as
,
OP_POP_RLIST_PC
(
as
->
push_reglist
));
}
void
asm_thumb_label_assign
(
asm_thumb_t
*
as
,
uint
label
)
{
assert
(
label
<
as
->
max_num_labels
);
if
(
as
->
pass
<
ASM_THUMB_PASS_EMIT
)
{
// assign label offset
assert
(
as
->
label_offsets
[
label
]
==
-
1
);
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);
assert
(
as
->
label_offsets
[
label
]
==
as
->
code_offset
);
}
}
void
asm_thumb_align
(
asm_thumb_t
*
as
,
uint
align
)
{
// TODO fill unused data with NOPs?
as
->
code_offset
=
(
as
->
code_offset
+
align
-
1
)
&
(
~
(
align
-
1
));
}
void
asm_thumb_data
(
asm_thumb_t
*
as
,
uint
bytesize
,
uint
val
)
{
byte
*
c
=
asm_thumb_get_cur_to_write_bytes
(
as
,
bytesize
);
// only write to the buffer in the emit pass (otherwise we overflow dummy_data)
if
(
as
->
pass
==
ASM_THUMB_PASS_EMIT
)
{
// little endian
for
(
uint
i
=
0
;
i
<
bytesize
;
i
++
)
{
*
c
++
=
val
;
val
>>=
8
;
}
}
}
STATIC
mp_uint_t
get_label_dest
(
asm_thumb_t
*
as
,
uint
label
)
{
assert
(
label
<
as
->
max_num_labels
);
return
as
->
label_offsets
[
label
];
assert
(
label
<
as
->
base
.
max_num_labels
);
return
as
->
base
.
label_offsets
[
label
];
}
void
asm_thumb_op16
(
asm_thumb_t
*
as
,
uint
op
)
{
...
...
@@ -309,10 +211,10 @@ void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_
bool
asm_thumb_b_n_label
(
asm_thumb_t
*
as
,
uint
label
)
{
mp_uint_t
dest
=
get_label_dest
(
as
,
label
);
mp_int_t
rel
=
dest
-
as
->
code_offset
;
mp_int_t
rel
=
dest
-
as
->
base
.
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
asm_thumb_op16
(
as
,
OP_B_N
(
rel
));
return
as
->
pass
!=
ASM
_THUMB
_PASS_EMIT
||
SIGNED_FIT12
(
rel
);
return
as
->
base
.
pass
!=
MP_
ASM_PASS_EMIT
||
SIGNED_FIT12
(
rel
);
}
#define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff))
...
...
@@ -323,11 +225,11 @@ bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) {
bool
asm_thumb_bcc_nw_label
(
asm_thumb_t
*
as
,
int
cond
,
uint
label
,
bool
wide
)
{
mp_uint_t
dest
=
get_label_dest
(
as
,
label
);
mp_int_t
rel
=
dest
-
as
->
code_offset
;
mp_int_t
rel
=
dest
-
as
->
base
.
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
if
(
!
wide
)
{
asm_thumb_op16
(
as
,
OP_BCC_N
(
cond
,
rel
));
return
as
->
pass
!=
ASM
_THUMB
_PASS_EMIT
||
SIGNED_FIT9
(
rel
);
return
as
->
base
.
pass
!=
MP_
ASM_PASS_EMIT
||
SIGNED_FIT9
(
rel
);
}
else
{
asm_thumb_op32
(
as
,
OP_BCC_W_HI
(
cond
,
rel
),
OP_BCC_W_LO
(
rel
));
return
true
;
...
...
@@ -339,10 +241,10 @@ bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) {
bool
asm_thumb_bl_label
(
asm_thumb_t
*
as
,
uint
label
)
{
mp_uint_t
dest
=
get_label_dest
(
as
,
label
);
mp_int_t
rel
=
dest
-
as
->
code_offset
;
mp_int_t
rel
=
dest
-
as
->
base
.
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
asm_thumb_op32
(
as
,
OP_BL_HI
(
rel
),
OP_BL_LO
(
rel
));
return
as
->
pass
!=
ASM
_THUMB
_PASS_EMIT
||
SIGNED_FIT23
(
rel
);
return
as
->
base
.
pass
!=
MP_
ASM_PASS_EMIT
||
SIGNED_FIT23
(
rel
);
}
void
asm_thumb_mov_reg_i32
(
asm_thumb_t
*
as
,
uint
reg_dest
,
mp_uint_t
i32
)
{
...
...
@@ -367,13 +269,13 @@ void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) {
// TODO this is very inefficient, improve it!
void
asm_thumb_mov_reg_i32_aligned
(
asm_thumb_t
*
as
,
uint
reg_dest
,
int
i32
)
{
// align on machine-word + 2
if
((
as
->
code_offset
&
3
)
==
0
)
{
if
((
as
->
base
.
code_offset
&
3
)
==
0
)
{
asm_thumb_op16
(
as
,
ASM_THUMB_OP_NOP
);
}
// jump over the i32 value (instruction prefetch adds 2 to PC)
asm_thumb_op16
(
as
,
OP_B_N
(
2
));
// store i32 on machine-word aligned boundary
asm_
thumb
_data
(
as
,
4
,
i32
);
mp_
asm_
base
_data
(
&
as
->
base
,
4
,
i32
);
// do the actual load of the i32 value
asm_thumb_mov_reg_i32_optimised
(
as
,
reg_dest
,
i32
);
}
...
...
@@ -384,14 +286,14 @@ void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) {
void
asm_thumb_mov_local_reg
(
asm_thumb_t
*
as
,
int
local_num
,
uint
rlo_src
)
{
assert
(
rlo_src
<
ASM_THUMB_REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM
_THUMB
_PASS_EMIT
||
word_offset
>=
0
);
assert
(
as
->
base
.
pass
<
MP_
ASM_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
<
ASM_THUMB_REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM
_THUMB
_PASS_EMIT
||
word_offset
>=
0
);
assert
(
as
->
base
.
pass
<
MP_
ASM_PASS_EMIT
||
word_offset
>=
0
);
asm_thumb_op16
(
as
,
OP_LDR_FROM_SP_OFFSET
(
rlo_dest
,
word_offset
));
}
...
...
@@ -400,7 +302,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
void
asm_thumb_mov_reg_local_addr
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
int
local_num
)
{
assert
(
rlo_dest
<
ASM_THUMB_REG_R8
);
int
word_offset
=
local_num
;
assert
(
as
->
pass
<
ASM
_THUMB
_PASS_EMIT
||
word_offset
>=
0
);
assert
(
as
->
base
.
pass
<
MP_
ASM_PASS_EMIT
||
word_offset
>=
0
);
asm_thumb_op16
(
as
,
OP_ADD_REG_SP_OFFSET
(
rlo_dest
,
word_offset
));
}
...
...
@@ -410,7 +312,7 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
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
;
mp_int_t
rel
=
dest
-
as
->
base
.
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
if
(
dest
!=
(
mp_uint_t
)
-
1
&&
rel
<=
-
4
)
{
// is a backwards jump, so we know the size of the jump on the first pass
...
...
@@ -429,7 +331,7 @@ void asm_thumb_b_label(asm_thumb_t *as, uint label) {
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
;
mp_int_t
rel
=
dest
-
as
->
base
.
code_offset
;
rel
-=
4
;
// account for instruction prefetch, PC is 4 bytes ahead of this instruction
if
(
dest
!=
(
mp_uint_t
)
-
1
&&
rel
<=
-
4
)
{
// is a backwards jump, so we know the size of the jump on the first pass
...
...
py/asmthumb.h
View file @
61259958
...
...
@@ -27,9 +27,7 @@
#define __MICROPY_INCLUDED_PY_ASMTHUMB_H__
#include
"py/misc.h"
#define ASM_THUMB_PASS_COMPUTE (1)
#define ASM_THUMB_PASS_EMIT (2)
#include
"py/asmbase.h"
#define ASM_THUMB_REG_R0 (0)
#define ASM_THUMB_REG_R1 (1)
...
...
@@ -64,24 +62,17 @@
#define ASM_THUMB_CC_GT (0xc)
#define ASM_THUMB_CC_LE (0xd)
typedef
struct
_asm_thumb_t
asm_thumb_t
;
typedef
struct
_asm_thumb_t
{
mp_asm_base_t
base
;
uint32_t
push_reglist
;
uint32_t
stack_adjust
;
}
asm_thumb_t
;
asm_thumb_t
*
asm_thumb_new
(
uint
max_num_labels
);
void
asm_thumb_free
(
asm_thumb_t
*
as
,
bool
free_code
);
void
asm_thumb_start_pass
(
asm_thumb_t
*
as
,
uint
pass
);
void
asm_thumb_end_pass
(
asm_thumb_t
*
as
);
uint
asm_thumb_get_code_pos
(
asm_thumb_t
*
as
);
uint
asm_thumb_get_code_size
(
asm_thumb_t
*
as
);
void
*
asm_thumb_get_code
(
asm_thumb_t
*
as
);
void
asm_thumb_entry
(
asm_thumb_t
*
as
,
int
num_locals
);
void
asm_thumb_exit
(
asm_thumb_t
*
as
);
void
asm_thumb_label_assign
(
asm_thumb_t
*
as
,
uint
label
);
void
asm_thumb_align
(
asm_thumb_t
*
as
,
uint
align
);
void
asm_thumb_data
(
asm_thumb_t
*
as
,
uint
bytesize
,
uint
val
);
// argument order follows ARM, in general dest is first
// note there is a difference between movw and mov.w, and many others!
...
...
py/asmx64.c
View file @
61259958
...
...
@@ -116,80 +116,8 @@
#define UNSIGNED_FIT32(x) (((x) & 0xffffffff00000000) == 0)
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
struct
_asm_x64_t
{
uint
pass
;
mp_uint_t
code_offset
;
mp_uint_t
code_size
;
byte
*
code_base
;
byte
dummy_data
[
8
];
mp_uint_t
max_num_labels
;
mp_uint_t
*
label_offsets
;
int
num_locals
;
};
asm_x64_t
*
asm_x64_new
(
mp_uint_t
max_num_labels
)
{