|
|
@@ -26,7 +26,20 @@ void free_alternatives_memory(void);
|
|
|
" .byte 662b-661b\n" /* source len */ \
|
|
|
" .byte 664f-663f\n" /* replacement len */
|
|
|
|
|
|
-/* alternative assembly primitive: */
|
|
|
+/*
|
|
|
+ * alternative assembly primitive:
|
|
|
+ *
|
|
|
+ * If any of these .org directive fail, it means that insn1 and insn2
|
|
|
+ * don't have the same length. This used to be written as
|
|
|
+ *
|
|
|
+ * .if ((664b-663b) != (662b-661b))
|
|
|
+ * .error "Alternatives instruction length mismatch"
|
|
|
+ * .endif
|
|
|
+ *
|
|
|
+ * but most assemblers die if insn1 or insn2 have a .inst. This should
|
|
|
+ * be fixed in a binutils release posterior to 2.25.51.0.2 (anything
|
|
|
+ * containing commit 4e4d08cf7399b606 or c1baaddf8861).
|
|
|
+ */
|
|
|
#define ALTERNATIVE(oldinstr, newinstr, feature) \
|
|
|
"661:\n\t" \
|
|
|
oldinstr "\n" \
|
|
|
@@ -39,9 +52,8 @@ void free_alternatives_memory(void);
|
|
|
newinstr "\n" \
|
|
|
"664:\n\t" \
|
|
|
".popsection\n\t" \
|
|
|
- ".if ((664b-663b) != (662b-661b))\n\t" \
|
|
|
- " .error \"Alternatives instruction length mismatch\"\n\t"\
|
|
|
- ".endif\n"
|
|
|
+ ".org . - (664b-663b) + (662b-661b)\n\t" \
|
|
|
+ ".org . - (662b-661b) + (664b-663b)\n"
|
|
|
|
|
|
#else
|
|
|
|
|
|
@@ -61,9 +73,8 @@ void free_alternatives_memory(void);
|
|
|
.pushsection .altinstr_replacement, "ax"
|
|
|
663: \insn2
|
|
|
664: .popsection
|
|
|
- .if ((664b-663b) != (662b-661b))
|
|
|
- .error "Alternatives instruction length mismatch"
|
|
|
- .endif
|
|
|
+ .org . - (664b-663b) + (662b-661b)
|
|
|
+ .org . - (662b-661b) + (664b-663b)
|
|
|
.endm
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|