+
+/* COMMPAGE_CALL(target,from,start)
+ *
+ * This macro compiles a relative near call to one
+ * commpage routine from another.
+ * The assembler cannot handle this directly because the code
+ * is not being assembled at the address at which it will execute.
+ * The alternative to this macro would be to use an
+ * indirect call, which is slower because the target of an
+ * indirect branch is poorly predicted.
+ * The macro arguments are:
+ * target = the commpage routine we are calling
+ * from = the commpage routine we are in now
+ * start = the label at the start of the code for this func
+ * This is admitedly ugly and fragile. Is there a better way?
+ */
+#define COMMPAGE_CALL(target, from, start) \
+ COMMPAGE_CALL_INTERNAL(target,from,start,__LINE__)
+
+#define COMMPAGE_CALL_INTERNAL(target, from, start, unique) \
+ .byte 0xe8 ;\
+.set UNIQUEID(unique), L ## start - . + target - from - 4 ;\
+ .long UNIQUEID(unique)
+
+#define UNIQUEID(name) L ## name
+
+/* COMMPAGE_JMP(target,from,start)
+ *
+ * This macro perform a jump to another commpage routine.
+ * Used to return from the PFZ by jumping via a return outside the PFZ.
+ */
+#define COMMPAGE_JMP(target, from, start) \
+ jmp L ## start - from + target
+