Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
micropython
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
card10
micropython
Commits
47e1b85d
Commit
47e1b85d
authored
11 years ago
by
Damien George
Browse files
Options
Downloads
Patches
Plain Diff
py: Improve inline assembler; add a few more opcodes.
parent
495d781a
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
py/asmthumb.c
+16
-16
16 additions, 16 deletions
py/asmthumb.c
py/asmthumb.h
+3
-4
3 additions, 4 deletions
py/asmthumb.h
py/emitinlinethumb.c
+99
-64
99 additions, 64 deletions
py/emitinlinethumb.c
with
118 additions
and
84 deletions
py/asmthumb.c
+
16
−
16
View file @
47e1b85d
...
...
@@ -275,6 +275,12 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
asm_thumb_write_op16
(
as
,
0x4600
|
op_lo
);
}
#define OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest))
void
asm_thumb_add_reg_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src_a
,
uint
rlo_src_b
)
{
asm_thumb_write_op16
(
as
,
OP_ADD_REG_REG_REG
(
rlo_dest
,
rlo_src_a
,
rlo_src_b
));
}
#define OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src) (0x1e00 | ((i3_src) << 6) | ((rlo_src) << 3) | (rlo_dest))
void
asm_thumb_subs_rlo_rlo_i3
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src
,
int
i3_src
)
{
...
...
@@ -283,6 +289,12 @@ void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int
asm_thumb_write_op16
(
as
,
OP_SUBS_RLO_RLO_I3
(
rlo_dest
,
rlo_src
,
i3_src
));
}
#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a))
void
asm_thumb_cmp_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_a
,
uint
rlo_b
)
{
asm_thumb_write_op16
(
as
,
OP_CMP_REG_REG
(
rlo_a
,
rlo_b
));
}
#define OP_CMP_RLO_I8(rlo, i8) (0x2800 | ((rlo) << 8) | (i8))
void
asm_thumb_cmp_rlo_i8
(
asm_thumb_t
*
as
,
uint
rlo
,
int
i8
)
{
...
...
@@ -290,6 +302,10 @@ 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
));
}
void
asm_thumb_ite_ge
(
asm_thumb_t
*
as
)
{
asm_thumb_write_op16
(
as
,
0xbfac
);
}
#define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))
void
asm_thumb_b_n
(
asm_thumb_t
*
as
,
int
label
)
{
...
...
@@ -360,22 +376,6 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
asm_thumb_write_op16
(
as
,
OP_ADD_REG_SP_OFFSET
(
rlo_dest
,
word_offset
));
}
#define OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest))
void
asm_thumb_add_reg_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src_a
,
uint
rlo_src_b
)
{
asm_thumb_write_op16
(
as
,
OP_ADD_REG_REG_REG
(
rlo_dest
,
rlo_src_a
,
rlo_src_b
));
}
#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a))
void
asm_thumb_cmp_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_a
,
uint
rlo_b
)
{
asm_thumb_write_op16
(
as
,
OP_CMP_REG_REG
(
rlo_a
,
rlo_b
));
}
void
asm_thumb_ite_ge
(
asm_thumb_t
*
as
)
{
asm_thumb_write_op16
(
as
,
0xbfac
);
}
// 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_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
...
...
This diff is collapsed.
Click to expand it.
py/asmthumb.h
+
3
−
4
View file @
47e1b85d
...
...
@@ -62,8 +62,11 @@ void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src);
void
asm_thumb_movw_reg_i16
(
asm_thumb_t
*
as
,
uint
reg_dest
,
int
i16_src
);
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_add_reg_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src_a
,
uint
rlo_src_b
);
void
asm_thumb_subs_rlo_rlo_i3
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src
,
int
i3_src
);
void
asm_thumb_cmp_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_a
,
uint
rlo_b
);
void
asm_thumb_cmp_rlo_i8
(
asm_thumb_t
*
as
,
uint
rlo
,
int
i8
);
void
asm_thumb_ite_ge
(
asm_thumb_t
*
as
);
void
asm_thumb_b_n
(
asm_thumb_t
*
as
,
int
label
);
void
asm_thumb_bcc_n
(
asm_thumb_t
*
as
,
int
cond
,
int
label
);
...
...
@@ -73,10 +76,6 @@ void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src);
void
asm_thumb_mov_reg_local
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
int
local_num
);
// convenience
void
asm_thumb_mov_reg_local_addr
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
int
local_num
);
// convenience
void
asm_thumb_add_reg_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_dest
,
uint
rlo_src_a
,
uint
rlo_src_b
);
// convenience ?
void
asm_thumb_cmp_reg_reg
(
asm_thumb_t
*
as
,
uint
rlo_a
,
uint
rlo_b
);
// convenience ?
void
asm_thumb_ite_ge
(
asm_thumb_t
*
as
);
// convenience ?
void
asm_thumb_b_label
(
asm_thumb_t
*
as
,
int
label
);
// convenience ?
void
asm_thumb_bcc_label
(
asm_thumb_t
*
as
,
int
cc
,
int
label
);
// convenience: picks narrow or wide branch
void
asm_thumb_bl_ind
(
asm_thumb_t
*
as
,
void
*
fun_ptr
,
uint
fun_id
,
uint
reg_temp
);
// convenience ?
...
...
This diff is collapsed.
Click to expand it.
py/emitinlinethumb.c
+
99
−
64
View file @
47e1b85d
...
...
@@ -81,45 +81,36 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, int label_num, qstr
asm_thumb_label_assign
(
emit
->
as
,
label_num
);
}
STATIC
bool
check_n_arg
(
qstr
op
,
int
n_args
,
int
wanted_n_args
)
{
if
(
wanted_n_args
==
n_args
)
{
return
true
;
}
else
{
printf
(
"SyntaxError: '%s' expects %d arguments'
\n
"
,
qstr_str
(
op
),
wanted_n_args
);
return
false
;
}
}
STATIC
uint
get_arg_rlo
(
qstr
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
)
{
STATIC
uint
get_arg_rlo
(
const
char
*
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
)
{
if
(
!
MP_PARSE_NODE_IS_ID
(
pn_args
[
wanted_arg_num
]))
{
printf
(
"SyntaxError: '%s' expects a register in position %d
\n
"
,
qstr_str
(
op
)
,
wanted_arg_num
);
printf
(
"SyntaxError: '%s' expects a register in position %d
\n
"
,
op
,
wanted_arg_num
);
return
0
;
}
qstr
reg_qstr
=
MP_PARSE_NODE_LEAF_ARG
(
pn_args
[
wanted_arg_num
]);
const
char
*
reg_str
=
qstr_str
(
reg_qstr
);
if
(
!
(
strlen
(
reg_str
)
==
2
&&
reg_str
[
0
]
==
'r'
&&
(
'0'
<=
reg_str
[
1
]
&&
reg_str
[
1
]
<=
'7'
)))
{
printf
(
"SyntaxError: '%s' expects a register in position %d
\n
"
,
qstr_str
(
op
)
,
wanted_arg_num
);
printf
(
"SyntaxError: '%s' expects a register in position %d
\n
"
,
op
,
wanted_arg_num
);
return
0
;
}
return
reg_str
[
1
]
-
'0'
;
}
STATIC
int
get_arg_i
(
qst
r
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
,
int
fit_mask
)
{
STATIC
int
get_arg_i
(
const
cha
r
*
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
,
int
fit_mask
)
{
if
(
!
MP_PARSE_NODE_IS_SMALL_INT
(
pn_args
[
wanted_arg_num
]))
{
printf
(
"SyntaxError: '%s' expects an integer in position %d
\n
"
,
qstr_str
(
op
)
,
wanted_arg_num
);
printf
(
"SyntaxError: '%s' expects an integer in position %d
\n
"
,
op
,
wanted_arg_num
);
return
0
;
}
int
i
=
MP_PARSE_NODE_LEAF_SMALL_INT
(
pn_args
[
wanted_arg_num
]);
if
((
i
&
(
~
fit_mask
))
!=
0
)
{
printf
(
"SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x
\n
"
,
qstr_str
(
op
)
,
i
,
fit_mask
);
printf
(
"SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x
\n
"
,
op
,
i
,
fit_mask
);
return
0
;
}
return
i
;
}
STATIC
int
get_arg_label
(
emit_inline_asm_t
*
emit
,
qst
r
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
)
{
STATIC
int
get_arg_label
(
emit_inline_asm_t
*
emit
,
const
cha
r
*
op
,
mp_parse_node_t
*
pn_args
,
int
wanted_arg_num
)
{
if
(
!
MP_PARSE_NODE_IS_ID
(
pn_args
[
wanted_arg_num
]))
{
printf
(
"SyntaxError: '%s' expects a label in position %d
\n
"
,
qstr_str
(
op
)
,
wanted_arg_num
);
printf
(
"SyntaxError: '%s' expects a label in position %d
\n
"
,
op
,
wanted_arg_num
);
return
0
;
}
qstr
label_qstr
=
MP_PARSE_NODE_LEAF_ARG
(
pn_args
[
wanted_arg_num
]);
...
...
@@ -135,6 +126,24 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_a
return
0
;
}
typedef
struct
_cc_name_t
{
byte
cc
;
byte
name
[
2
];
}
cc_name_t
;
STATIC
const
cc_name_t
cc_name_table
[]
=
{
{
THUMB_CC_EQ
,
"eq"
},
{
THUMB_CC_NE
,
"ne"
},
{
THUMB_CC_CS
,
"cs"
},
{
THUMB_CC_CC
,
"cc"
},
{
THUMB_CC_MI
,
"mi"
},
{
THUMB_CC_PL
,
"pl"
},
{
THUMB_CC_VS
,
"vs"
},
{
THUMB_CC_VC
,
"vc"
},
{
THUMB_CC_HI
,
"hi"
},
{
THUMB_CC_LS
,
"ls"
},
{
THUMB_CC_GE
,
"ge"
},
{
THUMB_CC_LT
,
"lt"
},
{
THUMB_CC_GT
,
"gt"
},
{
THUMB_CC_LE
,
"le"
},
};
STATIC
void
emit_inline_thumb_op
(
emit_inline_asm_t
*
emit
,
qstr
op
,
int
n_args
,
mp_parse_node_t
*
pn_args
)
{
// TODO perhaps make two tables:
// one_args =
...
...
@@ -146,60 +155,86 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
// three_args =
// "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
// 1 arg
if
(
strcmp
(
qstr_str
(
op
),
"b"
)
==
0
)
{
if
(
!
check_n_arg
(
op
,
n_args
,
1
))
{
return
;
const
char
*
op_str
=
qstr_str
(
op
);
uint
op_len
=
strlen
(
op_str
);
if
(
n_args
==
0
)
{
if
(
strcmp
(
op_str
,
"ite.ge"
)
==
0
)
{
// TODO correct name for this op?
asm_thumb_ite_ge
(
emit
->
as
);
}
else
{
goto
unknown_op
;
}
int
label_num
=
get_arg_label
(
emit
,
op
,
pn_args
,
0
);
}
else
if
(
n_args
==
1
)
{
if
(
strcmp
(
op_str
,
"b"
)
==
0
)
{
int
label_num
=
get_arg_label
(
emit
,
op_str
,
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
))
{
return
;
}
else
if
(
op_str
[
0
]
==
'b'
&&
op_len
==
3
)
{
uint
cc
=
-
1
;
for
(
uint
i
=
0
;
i
<
(
sizeof
cc_name_table
)
/
(
sizeof
cc_name_table
[
0
]);
i
++
)
{
if
(
op_str
[
1
]
==
cc_name_table
[
i
].
name
[
0
]
&&
op_str
[
2
]
==
cc_name_table
[
i
].
name
[
1
])
{
cc
=
cc_name_table
[
i
].
cc
;
}
}
int
label_num
=
get_arg_label
(
emit
,
op
,
pn_args
,
0
);
if
(
cc
==
-
1
)
{
goto
unknown_op
;
}
int
label_num
=
get_arg_label
(
emit
,
op_str
,
pn_args
,
0
);
// TODO check that this succeeded, ie branch was within range
asm_thumb_bcc_n
(
emit
->
as
,
THUMB_CC_GT
,
label_num
);
// 2 args
}
else
if
(
strcmp
(
qstr_str
(
op
),
"movs"
)
==
0
)
{
if
(
!
check_n_arg
(
op
,
n_args
,
2
))
{
return
;
asm_thumb_bcc_n
(
emit
->
as
,
cc
,
label_num
);
}
else
{
goto
unknown_op
;
}
uint
rlo_dest
=
get_arg_rlo
(
op
,
pn_args
,
0
);
int
i_src
=
get_arg_i
(
op
,
pn_args
,
1
,
0xff
);
}
else
if
(
n_args
==
2
)
{
if
(
strcmp
(
op_str
,
"mov"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
uint
rlo_src
=
get_arg_rlo
(
op_str
,
pn_args
,
1
);
asm_thumb_mov_reg_reg
(
emit
->
as
,
rlo_dest
,
rlo_src
);
}
else
if
(
strcmp
(
op_str
,
"movs"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
int
i_src
=
get_arg_i
(
op_str
,
pn_args
,
1
,
0xff
);
asm_thumb_movs_rlo_i8
(
emit
->
as
,
rlo_dest
,
i_src
);
}
else
if
(
strcmp
(
qstr_str
(
op
),
"movw"
)
==
0
)
{
if
(
!
check_n_arg
(
op
,
n_args
,
2
))
{
return
;
}
uint
rlo_dest
=
get_arg_rlo
(
op
,
pn_args
,
0
);
// TODO can be reg lo or hi
int
i_src
=
get_arg_i
(
op
,
pn_args
,
1
,
0xffff
);
}
else
if
(
strcmp
(
op_str
,
"movw"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
// TODO can be reg lo or hi
int
i_src
=
get_arg_i
(
op_str
,
pn_args
,
1
,
0xffff
);
asm_thumb_movw_reg_i16
(
emit
->
as
,
rlo_dest
,
i_src
);
}
else
if
(
strcmp
(
qstr_str
(
op
),
"cmp"
)
==
0
)
{
if
(
!
check_n_arg
(
op
,
n_args
,
2
))
{
return
;
}
uint
rlo
=
get_arg_rlo
(
op
,
pn_args
,
0
);
int
i8
=
get_arg_i
(
op
,
pn_args
,
1
,
0xff
);
}
else
if
(
strcmp
(
op_str
,
"movt"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
// TODO can be reg lo or hi
int
i_src
=
get_arg_i
(
op_str
,
pn_args
,
1
,
0xffff
);
asm_thumb_movt_reg_i16
(
emit
->
as
,
rlo_dest
,
i_src
);
}
else
if
(
strcmp
(
op_str
,
"cmp"
)
==
0
)
{
uint
rlo
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
int
i8
=
get_arg_i
(
op_str
,
pn_args
,
1
,
0xff
);
asm_thumb_cmp_rlo_i8
(
emit
->
as
,
rlo
,
i8
);
// 3 args
}
else
if
(
strcmp
(
qstr_str
(
op
),
"subs"
)
==
0
)
{
if
(
!
check_n_arg
(
op
,
n_args
,
3
))
{
return
;
}
uint
rlo_dest
=
get_arg_rlo
(
op
,
pn_args
,
0
);
uint
rlo_src
=
get_arg_rlo
(
op
,
pn_args
,
1
);
int
i3_src
=
get_arg_i
(
op
,
pn_args
,
2
,
0x7
);
}
else
{
goto
unknown_op
;
}
}
else
if
(
n_args
==
3
)
{
if
(
strcmp
(
op_str
,
"add"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
uint
rlo_src_a
=
get_arg_rlo
(
op_str
,
pn_args
,
1
);
uint
rlo_src_b
=
get_arg_rlo
(
op_str
,
pn_args
,
2
);
asm_thumb_add_reg_reg_reg
(
emit
->
as
,
rlo_dest
,
rlo_src_a
,
rlo_src_b
);
}
else
if
(
strcmp
(
op_str
,
"subs"
)
==
0
)
{
uint
rlo_dest
=
get_arg_rlo
(
op_str
,
pn_args
,
0
);
uint
rlo_src
=
get_arg_rlo
(
op_str
,
pn_args
,
1
);
int
i3_src
=
get_arg_i
(
op_str
,
pn_args
,
2
,
0x7
);
asm_thumb_subs_rlo_rlo_i3
(
emit
->
as
,
rlo_dest
,
rlo_src
,
i3_src
);
}
else
{
goto
unknown_op
;
}
// unknown op
}
else
{
printf
(
"SyntaxError: unsupported ARM Thumb instruction '%s'
\n
"
,
qstr_str
(
op
));
return
;
goto
unknown_op
;
}
return
;
unknown_op:
printf
(
"SyntaxError: unsupported ARM Thumb instruction '%s' with %d arguments
\n
"
,
op_str
,
n_args
);
}
const
emit_inline_asm_method_table_t
emit_inline_thumb_method_table
=
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment