Skip to content

Commit ac0b81e

Browse files
committed
Add assembly trampoline to handle native functions more compactly
1 parent 56fa587 commit ac0b81e

7 files changed

Lines changed: 311 additions & 273 deletions

File tree

src/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,6 @@ target_compile_options(pawn PRIVATE
916916
-DAMX_ANSIONLY
917917
-DAMX_NODYNALOAD
918918
-DAMX_DONT_RELOCATE
919-
-DAMX_NATIVETABLE=pawn_natives
920919
$<$<CONFIG:DEBUG>: ${DEBUG_FLAGS}>
921920
$<$<CONFIG:RELEASE>: ${RELEASE_FLAGS}>
922921
$<$<COMPILE_LANGUAGE:CXX>: ${CXX_FLAGS}>

src/displayapp/screens/Pawn.cpp

Lines changed: 115 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum {
1111
PAWN_ERR_MISSINGHANDLER,
1212
PAWN_ERR_INVALIDSTRING,
1313
PAWN_ERR_INVALIDSETTING,
14+
PAWN_ERR_INVALIDTRAMPOLINE,
1415

1516
PAWN_ERR_FIRST = PAWN_ERR_PARAMCOUNT,
1617
};
@@ -50,12 +51,6 @@ static void event_handler(lv_obj_t* obj, lv_event_t event) {
5051
}
5152
}
5253

53-
static cell AMX_NATIVE_CALL F_lv_scr_act(AMX* amx, const cell* params) {
54-
ASSERT_PARAMS(0);
55-
56-
return (cell) lv_scr_act();
57-
}
58-
5954
static cell AMX_NATIVE_CALL F_lv_label_create(AMX* amx, const cell* params) {
6055
ASSERT_PARAMS(3);
6156

@@ -65,26 +60,6 @@ static cell AMX_NATIVE_CALL F_lv_label_create(AMX* amx, const cell* params) {
6560
return (cell) label;
6661
}
6762

68-
static cell AMX_NATIVE_CALL F_lv_btn_create(AMX* amx, const cell* params) {
69-
ASSERT_PARAMS(2);
70-
71-
return (cell) lv_btn_create(PARAMS_OBJ(1) ?: lv_scr_act(), PARAMS_OBJ(2));
72-
}
73-
74-
static cell AMX_NATIVE_CALL F_lv_obj_set_pos(AMX* amx, const cell* params) {
75-
ASSERT_PARAMS(3);
76-
77-
lv_obj_set_pos(PARAMS_OBJ(1), params[2], params[3]);
78-
return 0;
79-
}
80-
81-
static cell AMX_NATIVE_CALL F_lv_obj_set_size(AMX* amx, const cell* params) {
82-
ASSERT_PARAMS(3);
83-
84-
lv_obj_set_size(PARAMS_OBJ(1), params[2], params[3]);
85-
return 0;
86-
}
87-
8863
static cell AMX_NATIVE_CALL F_lv_obj_set_event_cb(AMX* amx, const cell* params) {
8964
ASSERT_PARAMS(2);
9065

@@ -164,25 +139,6 @@ static cell AMX_NATIVE_CALL F_lv_obj_set_style_local_ptr(AMX* amx, const cell* p
164139
return 0;
165140
}
166141

167-
static cell AMX_NATIVE_CALL F_lv_obj_align(AMX* amx, const cell* params) {
168-
ASSERT_PARAMS(5)
169-
170-
lv_obj_t* obj = PARAMS_OBJ(1);
171-
lv_obj_t* base = PARAMS_OBJ(2);
172-
cell align = params[3];
173-
cell x_ofs = params[4];
174-
cell y_ofs = params[5];
175-
176-
lv_obj_align(obj, base, align, x_ofs, y_ofs);
177-
return 0;
178-
}
179-
180-
static cell AMX_NATIVE_CALL F_lv_obj_realign(AMX* amx, const cell* params) {
181-
ASSERT_PARAMS(1)
182-
lv_obj_realign(PARAMS_OBJ(1));
183-
return 0;
184-
}
185-
186142
/**
187143
* Hand-written implementation of sprintf with limited functionality in order to support reading strings from parameters.
188144
* Supported interpolations:
@@ -401,6 +357,99 @@ static cell AMX_NATIVE_CALL F_raise_error(AMX* amx, const cell* params) {
401357
return 0;
402358
}
403359

360+
static const uintptr_t natives[] = { // Indices start at -1000
361+
(uintptr_t) lv_label_create,
362+
(uintptr_t) lv_btn_create,
363+
(uintptr_t) lv_obj_set_pos,
364+
(uintptr_t) lv_obj_set_size,
365+
(uintptr_t) lv_obj_align,
366+
(uintptr_t) lv_obj_realign,
367+
};
368+
369+
static const AMX_NATIVE lvgl_proxys[] = { // Indices start at -3000
370+
F_lv_label_create,
371+
F_lv_obj_set_event_cb,
372+
F_lv_label_set_text,
373+
F_lv_obj_set_style_local_int,
374+
F_lv_obj_set_style_local_color,
375+
F_lv_obj_set_style_local_opa,
376+
F_lv_obj_set_style_local_ptr,
377+
};
378+
379+
static const AMX_NATIVE pawn_proxys[] = { // Indices start at -2000
380+
F_sprintf,
381+
F_read_datetime,
382+
F_read_datetime_short_str,
383+
F_status_icons_create,
384+
F_status_icons_update,
385+
F_has_new_notifications,
386+
F_get_setting,
387+
F_get_heartrate,
388+
F_get_heartrate_state,
389+
F_get_step_number,
390+
F_raise_error,
391+
};
392+
393+
static cell trampoline(unsigned int index, const cell* params) {
394+
int param_count = params[0] / sizeof(cell);
395+
396+
if (index >= sizeof(natives) / sizeof(natives[0]))
397+
return PAWN_ERR_INVALIDTRAMPOLINE;
398+
399+
uintptr_t addr = natives[index] | 1; // Set lowest bit to enable thumb mode (always must be enabled on ARMv7-M)
400+
401+
cell ret;
402+
403+
params++; // Skip parameter count
404+
405+
asm volatile(".syntax unified\n"
406+
".thumb\n"
407+
408+
// Save stack pointer in case we push excess arguments into stack
409+
"mov r5, sp\n"
410+
411+
// Load first argument into R0 or jump out
412+
"subs %[count], #1\n"
413+
"bmi call\n"
414+
"ldr r0, [%[params]]\n"
415+
"add %[params], #4\n"
416+
417+
// Load second argument into R1 or jump out
418+
"subs %[count], #1\n"
419+
"bmi call\n"
420+
"ldr r1, [%[params]]\n"
421+
"add %[params], #4\n"
422+
423+
// Load third argument into R2 or jump out
424+
"subs %[count], #1\n"
425+
"bmi call\n"
426+
"ldr r2, [%[params]]\n"
427+
"add %[params], #4\n"
428+
429+
// Load fourth argument into R3 or jump out
430+
"subs %[count], #1\n"
431+
"bmi call\n"
432+
"ldr r3, [%[params]]\n"
433+
"add %[params], #4\n"
434+
435+
// Push remaining argument into stack in reverse order
436+
"loop: subs %[count], #1\n"
437+
" bmi call\n"
438+
" ldr r12, [%[params], +%[count], LSL 2]\n"
439+
" push {r12}\n"
440+
" b loop\n"
441+
442+
"call: blx %[addr]\n" // Call function
443+
" mov sp, r5\n" // Restore stack
444+
" mov %[ret], r0\n" // Move returned value into ret
445+
446+
: [ret] "=r"(ret), [count] "+r"(param_count), [params] "+r"(params)
447+
: [addr] "r"(addr)
448+
: "r0", "r1", "r2", "r3", "r5", "r12", "lr", "memory");
449+
450+
return ret;
451+
}
452+
404453
static int AMXAPI prun_Overlay(AMX* amx, int index) {
405454
AMX_HEADER* hdr;
406455
AMX_OVERLAYINFO* tbl;
@@ -421,6 +470,20 @@ static int AMXAPI prun_Overlay(AMX* amx, int index) {
421470
return AMX_ERR_NONE;
422471
}
423472

473+
static int AMXAPI prun_Callback(struct tagAMX* amx, cell index, cell* result, const cell* params) {
474+
amx->error = AMX_ERR_NONE;
475+
476+
if (index <= -3000) { // LVGL proxys
477+
*result = lvgl_proxys[-(index + 3000)](amx, params);
478+
} else if (index <= -2000) { // InfiniTime proxys
479+
*result = pawn_proxys[-(index + 2000)](amx, params);
480+
} else { // Direct trampolines
481+
*result = trampoline(-(index + 1000), params);
482+
}
483+
484+
return amx->error;
485+
}
486+
424487
int Pawn::LoadProgram() {
425488
int result;
426489
AMX_HEADER hdr;
@@ -483,33 +546,6 @@ int Pawn::LoadProgram() {
483546
return result;
484547
}
485548

486-
extern "C" const AMX_NATIVE pawn_natives[] = {
487-
F_sprintf,
488-
F_lv_scr_act,
489-
F_lv_label_create,
490-
F_lv_btn_create,
491-
F_lv_obj_set_pos,
492-
F_lv_obj_set_size,
493-
F_lv_obj_set_event_cb,
494-
F_lv_obj_align,
495-
F_lv_obj_realign,
496-
F_lv_label_set_text,
497-
F_lv_obj_set_style_local_int,
498-
F_lv_obj_set_style_local_color,
499-
F_lv_obj_set_style_local_opa,
500-
F_lv_obj_set_style_local_ptr,
501-
F_read_datetime,
502-
F_read_datetime_short_str,
503-
F_status_icons_create,
504-
F_status_icons_update,
505-
F_has_new_notifications,
506-
F_get_setting,
507-
F_get_heartrate,
508-
F_get_heartrate_state,
509-
F_get_step_number,
510-
F_raise_error,
511-
};
512-
513549
#include "program.h"
514550

515551
Pawn::Pawn(AppControllers& controllers) : Pawn(program, controllers) {
@@ -525,9 +561,13 @@ Pawn::Pawn(const uint8_t* file, AppControllers& controllers) : controllers(contr
525561

526562
lv_obj_set_user_data(lv_scr_act(), &amx);
527563

528-
cell* font;
529-
if (amx_FindPubVar(&amx, "font_jmec", &font) == AMX_ERR_NONE)
530-
*font = (cell) &jetbrains_mono_extrabold_compressed;
564+
amx_SetCallback(&amx, prun_Callback);
565+
566+
cell* var;
567+
if (amx_FindPubVar(&amx, "font_jmec", &var) == AMX_ERR_NONE)
568+
*var = (cell) &jetbrains_mono_extrabold_compressed;
569+
if (amx_FindPubVar(&amx, "screen", &var) == AMX_ERR_NONE)
570+
*var = (cell) lv_scr_act();
531571

532572
result = amx_Exec(&amx, NULL, AMX_EXEC_MAIN);
533573
if (result != AMX_ERR_NONE) {

src/displayapp/screens/program.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
const unsigned char program[] = {
2-
0xb0, 0x00, 0x00, 0x00, 0xe0, 0xf1, 0x0b, 0x0b, 0x04, 0x00, 0x08, 0x00,
3-
0x40, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
4-
0x78, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
2+
0xc4, 0x00, 0x00, 0x00, 0xe0, 0xf1, 0x0b, 0x0b, 0x04, 0x00, 0x08, 0x00,
3+
0x50, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
4+
0x8c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
55
0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
6-
0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
7-
0x1f, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
8-
0x9c, 0x00, 0xfc, 0xff, 0x92, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
9-
0x8e, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff,
10-
0x0c, 0x00, 0x00, 0x00, 0x88, 0x00, 0xfc, 0xff, 0x8e, 0x00, 0x14, 0x00,
11-
0x8e, 0x00, 0x14, 0x00, 0x90, 0x00, 0xfc, 0xff, 0x70, 0x00, 0x00, 0x00,
12-
0xfb, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x92, 0x00, 0x04, 0x00,
13-
0x90, 0x00, 0xfc, 0xff, 0x70, 0x00, 0x00, 0x00, 0xf6, 0xff, 0xff, 0xff,
14-
0x08, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00,
15-
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x65, 0x48,
16-
0x6f, 0x77, 0x20, 0x6f, 0x00, 0x64, 0x6c, 0x72
6+
0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
7+
0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x73, 0x63,
8+
0x72, 0x65, 0x65, 0x6e, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00,
9+
0x1e, 0x00, 0x00, 0x00, 0x9c, 0x00, 0xfc, 0xff, 0x92, 0x00, 0x04, 0x00,
10+
0x8e, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
11+
0x48, 0xf4, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x88, 0x00, 0xfc, 0xff,
12+
0x8e, 0x00, 0x14, 0x00, 0x8e, 0x00, 0x14, 0x00, 0x90, 0x00, 0xfc, 0xff,
13+
0x70, 0x00, 0x00, 0x00, 0x16, 0xfc, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
14+
0x92, 0x00, 0x08, 0x00, 0x90, 0x00, 0xfc, 0xff, 0x70, 0x00, 0x00, 0x00,
15+
0x46, 0xf4, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x04, 0x00,
16+
0x66, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17+
0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x65, 0x48, 0x6f, 0x77, 0x20, 0x6f,
18+
0x00, 0x64, 0x6c, 0x72
1719
};
18-
unsigned int program_len = 176;
20+
unsigned int program_len = 196;

0 commit comments

Comments
 (0)