[aarch64-port-dev ] Fix overflows in immediate arithemtic

Andrew Haley aph at redhat.com
Fri Jul 26 04:12:58 PDT 2013


If a constant does not fit in an immediate field, generate some
number of MOV instructions and then perform the operation

Andrew.


# HG changeset patch
# User aph
# Date 1374773485 -3600
# Node ID d9453f3218eefad8a982bb928bbdfcbc727cb2b0
# Parent  42d265e6978f09e0fa9c6d0ec634f1fda662ed8e
Fix overflows in immediate arithemtic
If a constant does not fit in an immediate field, generate some
number of MOV instructions and then perform the operation

diff -r 42d265e6978f -r d9453f3218ee src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Jul 25 18:32:39 2013 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Jul 25 18:31:25 2013 +0100
@@ -1516,6 +1516,21 @@
   ldp(rfp, lr, Address(post(sp, 2 * wordSize)));
 }

+// If a constant does not fit in an immediate field, generate some
+// number of MOV instructions and then perform the operation
+void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
+					   add_sub_imm_insn insn1,
+					   add_sub_reg_insn insn2) {
+  if (operand_valid_for_add_sub_immediate((int)imm)) {
+    (this->*insn1)(Rd, Rn, imm);
+  } else {
+    assert_different_registers(Rd, Rn);
+    mov(Rd, (uint64_t)imm);
+    (this->*insn2)(Rd, Rn, Rd, LSL, 0);
+  }
+}
+
+
 #ifdef ASSERT
 static Register spill_registers[] = {
   rheapbase,
diff -r 42d265e6978f -r d9453f3218ee src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Jul 25 18:32:39 2013 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Jul 25 18:31:25 2013 +0100
@@ -143,17 +143,6 @@

   virtual void notify(int type);

-  // Overrides
-
-  void subsw(Register Rd, Register Rn, Register Rm,
-	     enum shift_kind kind, unsigned shift = 0) {
-    Assembler::subsw(Rd, Rn, Rm, kind, shift);
-  }
-
-  void subsw(Register Rd, Register Rn, Register Rm) {
-    Assembler::subsw(Rd, Rn, Rm);
-  }
-
   // aliases defined in AARCH64 spec


@@ -1229,17 +1218,37 @@
   void repne_scanw(Register addr, Register value, Register count,
 		   Register scratch);

-  // SUBSW with an arbitrary integer operand
-  virtual void subsw(Register Rd, Register Rn, unsigned imm) {
-    if (operand_valid_for_add_sub_immediate((int)imm)) {
-      Assembler::subsw(Rd, Rn, imm);
-    } else {
-      assert_different_registers(Rd, Rn);
-      movw(Rd, imm);
-      subsw(Rd, Rn, Rd);
-    }
+  typedef void (MacroAssembler::* add_sub_imm_insn)(Register Rd, Register Rn, unsigned imm);
+  typedef void (MacroAssembler::* add_sub_reg_insn)(Register Rd, Register Rn, Register Rm, enum shift_kind kind, unsigned shift);
+
+  // If a constant does not fit in an immediate field, generate some
+  // number of MOV instructions and then perform the operation
+  void wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
+			     add_sub_imm_insn insn1,
+			     add_sub_reg_insn insn2);
+
+#define WRAP(INSN)							\
+  void INSN(Register Rd, Register Rn, unsigned imm) {			\
+    wrap_add_sub_imm_insn(Rd, Rn, imm, &Assembler::INSN, &Assembler::INSN); \
+  }									\
+									\
+  void INSN(Register Rd, Register Rn, Register Rm,			\
+	     enum shift_kind kind, unsigned shift = 0) {		\
+    Assembler::INSN(Rd, Rn, Rm, kind, shift);				\
+  }									\
+									\
+  void INSN(Register Rd, Register Rn, Register Rm) {			\
+    Assembler::INSN(Rd, Rn, Rm);					\
+  }									\
+									\
+  void INSN(Register Rd, Register Rn, Register Rm,			\
+           ext::operation option, int amount = 0) {			\
+    Assembler::INSN(Rd, Rn, Rm, option, amount);			\
   }

+  WRAP(add) WRAP(addw) WRAP(sub) WRAP(subw)
+  WRAP(adds) WRAP(addsw) WRAP(subs) WRAP(subsw)
+
   void tableswitch(Register index, jint lowbound, jint highbound,
 		   Label &jumptable, Label &jumptable_end) {
     adr(rscratch1, jumptable);



More information about the aarch64-port-dev mailing list