Skip to content

Commit 03281b3

Browse files
committed
py: Allow x86 native functions to take arguments.
Fix some bugs with x86 stack and saving registers correctly.
1 parent c90f59e commit 03281b3

3 files changed

Lines changed: 46 additions & 30 deletions

File tree

py/asmx86.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
#define OPCODE_LEA_MEM_TO_R32 (0x8d) /* /r */
5555
#define OPCODE_XOR_R32_TO_RM32 (0x31) /* /r */
5656
#define OPCODE_ADD_R32_TO_RM32 (0x01)
57-
//#define OPCODE_ADD_I32_TO_RM32 (0x81) /* /0 */
58-
//#define OPCODE_ADD_I8_TO_RM32 (0x83) /* /0 */
57+
#define OPCODE_ADD_I32_TO_RM32 (0x81) /* /0 */
58+
#define OPCODE_ADD_I8_TO_RM32 (0x83) /* /0 */
5959
//#define OPCODE_SUB_R32_FROM_RM32 (0x29)
6060
#define OPCODE_SUB_I32_FROM_RM32 (0x81) /* /5 */
6161
#define OPCODE_SUB_I8_FROM_RM32 (0x83) /* /5 */
@@ -275,21 +275,17 @@ void asm_x86_add_r32_to_r32(asm_x86_t *as, int src_r32, int dest_r32) {
275275
asm_x86_write_byte_2(as, OPCODE_ADD_R32_TO_RM32, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
276276
}
277277

278-
#if 0
279-
void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32)
280-
{
281-
if (SIGNED_FIT8(src_i32))
282-
{
278+
void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) {
279+
if (SIGNED_FIT8(src_i32)) {
283280
asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
284281
asm_x86_write_byte_1(as, src_i32 & 0xff);
285-
}
286-
else
287-
{
282+
} else {
288283
asm_x86_write_byte_2(as, OPCODE_ADD_I32_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
289284
asm_x86_write_word32(as, src_i32);
290285
}
291286
}
292287

288+
#if 0
293289
void asm_x86_sub_r32_from_r32(asm_x86_t *as, int src_r32, int dest_r32) {
294290
asm_x86_write_byte_2(as, OPCODE_SUB_R32_FROM_RM32, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32));
295291
}
@@ -419,29 +415,33 @@ void asm_x86_entry(asm_x86_t *as, mp_uint_t num_locals) {
419415
asm_x86_mov_r32_to_r32(as, REG_ESP, REG_EBP);
420416
asm_x86_sub_i32_from_r32(as, num_locals * WORD_SIZE, REG_ESP);
421417
asm_x86_push_r32(as, REG_EBX);
418+
asm_x86_push_r32(as, REG_ESI);
419+
asm_x86_push_r32(as, REG_EDI);
420+
// TODO align stack on 16-byte boundary
422421
as->num_locals = num_locals;
423422
}
424423

425424
void asm_x86_exit(asm_x86_t *as) {
425+
asm_x86_pop_r32(as, REG_EDI);
426+
asm_x86_pop_r32(as, REG_ESI);
426427
asm_x86_pop_r32(as, REG_EBX);
427428
asm_x86_write_byte_1(as, OPCODE_LEAVE);
428429
asm_x86_ret(as);
429430
}
430431

431432
#if 0
432433
void asm_x86_push_arg(asm_x86_t *as, int src_arg_num) {
433-
assert(0);
434-
asm_x86_push_disp(as, REG_EBP, 8 + src_arg_num * WORD_SIZE);
434+
asm_x86_push_disp(as, REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE);
435435
}
436+
#endif
436437

437438
void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32) {
438-
assert(0);
439-
//asm_x86_mov_disp_to_r32(as, REG_EBP, 8 + src_arg_num * WORD_SIZE, dest_r32);
439+
asm_x86_mov_disp_to_r32(as, REG_EBP, 2 * WORD_SIZE + src_arg_num * WORD_SIZE, dest_r32);
440440
}
441441

442+
#if 0
442443
void asm_x86_mov_r32_to_arg(asm_x86_t *as, int src_r32, int dest_arg_num) {
443-
assert(0);
444-
//asm_x86_mov_r32_to_disp(as, src_r32, REG_EBP, 8 + dest_arg_num * WORD_SIZE);
444+
asm_x86_mov_r32_to_disp(as, src_r32, REG_EBP, 2 * WORD_SIZE + dest_arg_num * WORD_SIZE);
445445
}
446446
#endif
447447

@@ -491,6 +491,7 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32)
491491
#endif
492492

493493
void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32) {
494+
// TODO align stack on 16-byte boundary before the call
494495
assert(n_args <= 3);
495496
if (n_args > 2) {
496497
asm_x86_push_r32(as, REG_ARG_3);
@@ -515,6 +516,11 @@ void asm_x86_call_ind(asm_x86_t *as, void *ptr, mp_uint_t n_args, int temp_r32)
515516
asm_x86_write_byte_1(as, OPCODE_CALL_REL32);
516517
asm_x86_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
517518
*/
519+
520+
// the caller must clean up the stack
521+
if (n_args > 0) {
522+
asm_x86_add_i32_to_r32(as, WORD_SIZE * n_args, REG_ESP);
523+
}
518524
}
519525

520526
#endif // MICROPY_EMIT_X86

py/asmx86.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
// x86 cdecl calling convention is:
28+
// - args passed on the stack in reverse order
29+
// - return value in EAX
30+
// - caller cleans up the stack after a call
31+
// - stack must be aligned to 16-byte boundary before all calls
32+
// - EAX, ECX, EDX are caller-save
33+
// - EBX, ESI, EDI, EBP, ESP, EIP are callee-save
34+
2735
#define ASM_X86_PASS_COMPUTE (1)
2836
#define ASM_X86_PASS_EMIT (2)
2937

@@ -45,8 +53,8 @@
4553
#define ASM_X86_CC_JL (0xc) // less, signed
4654

4755
#define REG_RET REG_EAX
48-
#define REG_ARG_1 REG_EDI
49-
#define REG_ARG_2 REG_ESI
56+
#define REG_ARG_1 REG_EBX
57+
#define REG_ARG_2 REG_ECX
5058
#define REG_ARG_3 REG_EDX
5159

5260
typedef struct _asm_x86_t asm_x86_t;
@@ -71,6 +79,7 @@ void asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label);
7179
void asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label);
7280
void asm_x86_entry(asm_x86_t* as, mp_uint_t num_locals);
7381
void asm_x86_exit(asm_x86_t* as);
82+
void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32);
7483
void asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32);
7584
void asm_x86_mov_r32_to_local(asm_x86_t* as, int src_r32, int dest_local_num);
7685
void asm_x86_mov_local_addr_to_r32(asm_x86_t* as, int local_num, int dest_r32);

py/emitnative.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,12 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
190190
#define EXPORT_FUN(name) emit_native_x86_##name
191191

192192
#define REG_TEMP0 (REG_EAX)
193-
#define REG_TEMP1 (REG_EDI)
194-
#define REG_TEMP2 (REG_ESI)
193+
#define REG_TEMP1 (REG_EBX)
194+
#define REG_TEMP2 (REG_ECX)
195195

196-
#define REG_LOCAL_1 (REG_EBX)
197-
#define REG_LOCAL_NUM (1)
196+
#define REG_LOCAL_1 (REG_ESI)
197+
#define REG_LOCAL_2 (REG_EDI)
198+
#define REG_LOCAL_NUM (2)
198199

199200
#define ASM_PASS_COMPUTE ASM_X86_PASS_COMPUTE
200201
#define ASM_PASS_EMIT ASM_X86_PASS_EMIT
@@ -523,17 +524,13 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
523524
}
524525
#elif N_X86
525526
for (int i = 0; i < scope->num_pos_args; i++) {
526-
// TODO
527-
assert(0);
528527
if (i == 0) {
529-
asm_x86_mov_r32_to_r32(emit->as, REG_ARG_1, REG_LOCAL_1);
528+
asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_1);
530529
} else if (i == 1) {
531-
asm_x86_mov_r32_to_local(emit->as, REG_ARG_2, i - REG_LOCAL_NUM);
532-
} else if (i == 2) {
533-
asm_x86_mov_r32_to_local(emit->as, REG_ARG_3, i - REG_LOCAL_NUM);
530+
asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_2);
534531
} else {
535-
// TODO not implemented
536-
assert(0);
532+
asm_x86_mov_arg_to_r32(emit->as, i, REG_TEMP0);
533+
asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, i - REG_LOCAL_NUM);
537534
}
538535
}
539536
#elif N_THUMB
@@ -1023,6 +1020,8 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int lo
10231020
#elif N_X86
10241021
if (local_num == 0) {
10251022
emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1023+
} else if (local_num == 1) {
1024+
emit_post_push_reg(emit, vtype, REG_LOCAL_2);
10261025
} else {
10271026
need_reg_single(emit, REG_EAX, 0);
10281027
asm_x86_mov_local_to_r32(emit->as, local_num - REG_LOCAL_NUM, REG_EAX);
@@ -1124,6 +1123,8 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
11241123
#elif N_X86
11251124
if (local_num == 0) {
11261125
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1126+
} else if (local_num == 1) {
1127+
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
11271128
} else {
11281129
emit_pre_pop_reg(emit, &vtype, REG_EAX);
11291130
asm_x86_mov_r32_to_local(emit->as, REG_EAX, local_num - REG_LOCAL_NUM);

0 commit comments

Comments
 (0)