+static void *get_trampoline(const void *f)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(ndrc->tramp.f); i++) {
+ if (ndrc->tramp.f[i] == f || ndrc->tramp.f[i] == NULL)
+ break;
+ }
+ if (i == ARRAY_SIZE(ndrc->tramp.f)) {
+ SysPrintf("trampoline table is full, last func %p\n", f);
+ abort();
+ }
+ if (ndrc->tramp.f[i] == NULL) {
+ start_tcache_write(&ndrc->tramp.f[i], &ndrc->tramp.f[i + 1]);
+ ndrc->tramp.f[i] = f;
+ end_tcache_write(&ndrc->tramp.f[i], &ndrc->tramp.f[i + 1]);
+ }
+ return &ndrc->tramp.ops[i];
+}
+
+static void emit_far_jump(const void *f)
+{
+ if (can_jump_or_call(f)) {
+ emit_jmp(f);
+ return;
+ }
+
+ f = get_trampoline(f);
+ emit_jmp(f);
+}
+
+static void emit_far_call(const void *f)
+{
+ if (can_jump_or_call(f)) {
+ emit_call(f);
+ return;
+ }
+
+ f = get_trampoline(f);
+ emit_call(f);
+}
+