Skip to content

Commit e5de26d

Browse files
author
Jatin Bhateja
committedJun 20, 2024
8329032: C2 compiler register allocation support for APX EGPRs
Reviewed-by: kvn, sviswanathan
1 parent 4b4a483 commit e5de26d

26 files changed

+737
-185
lines changed
 

‎src/hotspot/cpu/x86/assembler_x86.cpp

+191-66
Large diffs are not rendered by default.

‎src/hotspot/cpu/x86/assembler_x86.hpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -530,14 +530,16 @@ class Assembler : public AbstractAssembler {
530530
};
531531

532532
enum PrefixBits {
533-
REXBIT_B = 0x01,
534-
REXBIT_X = 0x02,
535-
REXBIT_R = 0x04,
536-
REXBIT_W = 0x08,
533+
REX2BIT_B = 0x01,
534+
REX2BIT_X = 0x02,
535+
REX2BIT_R = 0x04,
536+
REX2BIT_W = 0x08,
537537
REX2BIT_B4 = 0x10,
538538
REX2BIT_X4 = 0x20,
539539
REX2BIT_R4 = 0x40,
540-
REX2BIT_M0 = 0x80
540+
REX2BIT_M0 = 0x80,
541+
REX2BIT_WB = 0x09,
542+
REX2BIT_WB4 = 0x18,
541543
};
542544

543545
enum VexPrefix {
@@ -1017,6 +1019,15 @@ class Assembler : public AbstractAssembler {
10171019

10181020
void pusha_uncached();
10191021
void popa_uncached();
1022+
1023+
// APX ISA extensions for register save/restore optimizations.
1024+
void push2(Register src1, Register src2, bool with_ppx = false);
1025+
void pop2(Register src1, Register src2, bool with_ppx = false);
1026+
void push2p(Register src1, Register src2);
1027+
void pop2p(Register src1, Register src2);
1028+
void pushp(Register src);
1029+
void popp(Register src);
1030+
10201031
#endif
10211032
void vzeroupper_uncached();
10221033
void decq(Register dst);
@@ -3070,7 +3081,6 @@ class InstructionAttr {
30703081
}
30713082

30723083
void set_extended_context(void) { _is_extended_context = true; }
3073-
30743084
};
30753085

30763086
#endif // CPU_X86_ASSEMBLER_X86_HPP

‎src/hotspot/cpu/x86/c1_Defs_x86.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ enum {
3939

4040
// registers
4141
enum {
42-
pd_nof_cpu_regs_frame_map = Register::number_of_registers, // number of registers used during code emission
42+
pd_nof_cpu_regs_frame_map = NOT_LP64(8) LP64_ONLY(16), // number of registers used during code emission
4343
pd_nof_fpu_regs_frame_map = FloatRegister::number_of_registers, // number of registers used during code emission
4444
pd_nof_xmm_regs_frame_map = XMMRegister::number_of_registers, // number of registers used during code emission
4545

‎src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2836,7 +2836,7 @@ void LIR_Assembler::align_call(LIR_Code code) {
28362836
offset += NativeCall::displacement_offset;
28372837
break;
28382838
case lir_icvirtual_call:
2839-
offset += NativeCall::displacement_offset + NativeMovConstReg::instruction_size;
2839+
offset += NativeCall::displacement_offset + NativeMovConstReg::instruction_size_rex;
28402840
break;
28412841
default: ShouldNotReachHere();
28422842
}
@@ -2873,7 +2873,7 @@ void LIR_Assembler::emit_static_call_stub() {
28732873
int start = __ offset();
28742874

28752875
// make sure that the displacement word of the call ends up word aligned
2876-
__ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset);
2876+
__ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size_rex + NativeCall::displacement_offset);
28772877
__ relocate(static_stub_Relocation::spec(call_pc));
28782878
__ mov_metadata(rbx, (Metadata*)nullptr);
28792879
// must be set to -1 at code generation time

‎src/hotspot/cpu/x86/c1_Runtime1_x86.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,12 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
420420
void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) {
421421
__ block_comment("save_live_registers");
422422

423-
__ pusha(); // integer registers
423+
// Push CPU state in multiple of 16 bytes
424+
#ifdef _LP64
425+
__ save_legacy_gprs();
426+
#else
427+
__ pusha();
428+
#endif
424429

425430
// assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset");
426431
// assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset");
@@ -560,7 +565,12 @@ void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) {
560565
__ block_comment("restore_live_registers");
561566

562567
restore_fpu(this, restore_fpu_registers);
568+
#ifdef _LP64
569+
__ restore_legacy_gprs();
570+
#else
563571
__ popa();
572+
#endif
573+
564574
}
565575

566576

‎src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,25 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) {
583583
caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg()));
584584
caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg()));
585585

586+
if (UseAPX) {
587+
caller_saved.Insert(OptoReg::as_OptoReg(r16->as_VMReg()));
588+
caller_saved.Insert(OptoReg::as_OptoReg(r17->as_VMReg()));
589+
caller_saved.Insert(OptoReg::as_OptoReg(r18->as_VMReg()));
590+
caller_saved.Insert(OptoReg::as_OptoReg(r19->as_VMReg()));
591+
caller_saved.Insert(OptoReg::as_OptoReg(r20->as_VMReg()));
592+
caller_saved.Insert(OptoReg::as_OptoReg(r21->as_VMReg()));
593+
caller_saved.Insert(OptoReg::as_OptoReg(r22->as_VMReg()));
594+
caller_saved.Insert(OptoReg::as_OptoReg(r23->as_VMReg()));
595+
caller_saved.Insert(OptoReg::as_OptoReg(r24->as_VMReg()));
596+
caller_saved.Insert(OptoReg::as_OptoReg(r25->as_VMReg()));
597+
caller_saved.Insert(OptoReg::as_OptoReg(r26->as_VMReg()));
598+
caller_saved.Insert(OptoReg::as_OptoReg(r27->as_VMReg()));
599+
caller_saved.Insert(OptoReg::as_OptoReg(r28->as_VMReg()));
600+
caller_saved.Insert(OptoReg::as_OptoReg(r29->as_VMReg()));
601+
caller_saved.Insert(OptoReg::as_OptoReg(r30->as_VMReg()));
602+
caller_saved.Insert(OptoReg::as_OptoReg(r31->as_VMReg()));
603+
}
604+
586605
int gp_spill_size = 0;
587606
int opmask_spill_size = 0;
588607
int xmm_spill_size = 0;

‎src/hotspot/cpu/x86/gc/x/xBarrierSetAssembler_x86.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,25 @@ class XSaveLiveRegisters {
484484
caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg()));
485485
caller_saved.Remove(OptoReg::as_OptoReg(stub->ref()->as_VMReg()));
486486

487+
if (UseAPX) {
488+
caller_saved.Insert(OptoReg::as_OptoReg(r16->as_VMReg()));
489+
caller_saved.Insert(OptoReg::as_OptoReg(r17->as_VMReg()));
490+
caller_saved.Insert(OptoReg::as_OptoReg(r18->as_VMReg()));
491+
caller_saved.Insert(OptoReg::as_OptoReg(r19->as_VMReg()));
492+
caller_saved.Insert(OptoReg::as_OptoReg(r20->as_VMReg()));
493+
caller_saved.Insert(OptoReg::as_OptoReg(r21->as_VMReg()));
494+
caller_saved.Insert(OptoReg::as_OptoReg(r22->as_VMReg()));
495+
caller_saved.Insert(OptoReg::as_OptoReg(r23->as_VMReg()));
496+
caller_saved.Insert(OptoReg::as_OptoReg(r24->as_VMReg()));
497+
caller_saved.Insert(OptoReg::as_OptoReg(r25->as_VMReg()));
498+
caller_saved.Insert(OptoReg::as_OptoReg(r26->as_VMReg()));
499+
caller_saved.Insert(OptoReg::as_OptoReg(r27->as_VMReg()));
500+
caller_saved.Insert(OptoReg::as_OptoReg(r28->as_VMReg()));
501+
caller_saved.Insert(OptoReg::as_OptoReg(r29->as_VMReg()));
502+
caller_saved.Insert(OptoReg::as_OptoReg(r30->as_VMReg()));
503+
caller_saved.Insert(OptoReg::as_OptoReg(r31->as_VMReg()));
504+
}
505+
487506
// Create mask of live registers
488507
RegMask live = stub->live();
489508
if (stub->tmp() != noreg) {

‎src/hotspot/cpu/x86/globals_x86.hpp

-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
115115
"Highest supported AVX instructions set on x86/x64") \
116116
range(0, 3) \
117117
\
118-
\
119118
product(bool, UseAPX, false, EXPERIMENTAL, \
120119
"Use Intel Advanced Performance Extensions") \
121120
\
@@ -192,7 +191,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
192191
product(bool, IntelJccErratumMitigation, true, DIAGNOSTIC, \
193192
"Turn off JVM mitigations related to Intel micro code " \
194193
"mitigations for the Intel JCC erratum") \
195-
\
196194
// end of ARCH_FLAGS
197195

198196
#endif // CPU_X86_GLOBALS_X86_HPP

‎src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMC
4949
return (pc_offset + NativeCall::instruction_size);
5050
} else if (inst->is_mov_literal64()) {
5151
// mov+call instruction pair
52-
jint offset = pc_offset + NativeMovConstReg::instruction_size;
52+
jint offset = pc_offset + ((NativeMovConstReg*)inst)->instruction_size();
5353
u_char* call = (u_char*) (_instructions->start() + offset);
5454
if (call[0] == Assembler::REX_B) {
5555
offset += 1; /* prefix byte for extended register R8-R15 */
5656
call++;
5757
}
58+
if (call[0] == Assembler::REX2) {
59+
offset += 2; /* prefix byte for APX extended GPR register R16-R31 */
60+
call+=2;
61+
}
62+
// Register indirect call.
5863
assert(call[0] == 0xFF, "expected call");
5964
offset += 2; /* opcode byte + modrm byte */
6065
return (offset);

‎src/hotspot/cpu/x86/macroAssembler_x86.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -4087,6 +4087,11 @@ RegSet MacroAssembler::call_clobbered_gp_registers() {
40874087
regs += RegSet::range(r8, r11);
40884088
#else
40894089
regs += RegSet::of(rax, rcx, rdx);
4090+
#endif
4091+
#ifdef _LP64
4092+
if (UseAPX) {
4093+
regs += RegSet::range(r16, as_Register(Register::number_of_registers - 1));
4094+
}
40904095
#endif
40914096
return regs;
40924097
}
@@ -10379,3 +10384,45 @@ void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register
1037910384

1038010385
bind(unlocked);
1038110386
}
10387+
10388+
#ifdef _LP64
10389+
// Saves legacy GPRs state on stack.
10390+
void MacroAssembler::save_legacy_gprs() {
10391+
subq(rsp, 16 * wordSize);
10392+
movq(Address(rsp, 15 * wordSize), rax);
10393+
movq(Address(rsp, 14 * wordSize), rcx);
10394+
movq(Address(rsp, 13 * wordSize), rdx);
10395+
movq(Address(rsp, 12 * wordSize), rbx);
10396+
movq(Address(rsp, 10 * wordSize), rbp);
10397+
movq(Address(rsp, 9 * wordSize), rsi);
10398+
movq(Address(rsp, 8 * wordSize), rdi);
10399+
movq(Address(rsp, 7 * wordSize), r8);
10400+
movq(Address(rsp, 6 * wordSize), r9);
10401+
movq(Address(rsp, 5 * wordSize), r10);
10402+
movq(Address(rsp, 4 * wordSize), r11);
10403+
movq(Address(rsp, 3 * wordSize), r12);
10404+
movq(Address(rsp, 2 * wordSize), r13);
10405+
movq(Address(rsp, wordSize), r14);
10406+
movq(Address(rsp, 0), r15);
10407+
}
10408+
10409+
// Resotres back legacy GPRs state from stack.
10410+
void MacroAssembler::restore_legacy_gprs() {
10411+
movq(r15, Address(rsp, 0));
10412+
movq(r14, Address(rsp, wordSize));
10413+
movq(r13, Address(rsp, 2 * wordSize));
10414+
movq(r12, Address(rsp, 3 * wordSize));
10415+
movq(r11, Address(rsp, 4 * wordSize));
10416+
movq(r10, Address(rsp, 5 * wordSize));
10417+
movq(r9, Address(rsp, 6 * wordSize));
10418+
movq(r8, Address(rsp, 7 * wordSize));
10419+
movq(rdi, Address(rsp, 8 * wordSize));
10420+
movq(rsi, Address(rsp, 9 * wordSize));
10421+
movq(rbp, Address(rsp, 10 * wordSize));
10422+
movq(rbx, Address(rsp, 12 * wordSize));
10423+
movq(rdx, Address(rsp, 13 * wordSize));
10424+
movq(rcx, Address(rsp, 14 * wordSize));
10425+
movq(rax, Address(rsp, 15 * wordSize));
10426+
addq(rsp, 16 * wordSize);
10427+
}
10428+
#endif

‎src/hotspot/cpu/x86/macroAssembler_x86.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -2150,6 +2150,11 @@ class MacroAssembler: public Assembler {
21502150

21512151
void lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
21522152
void lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
2153+
2154+
#ifdef _LP64
2155+
void save_legacy_gprs();
2156+
void restore_legacy_gprs();
2157+
#endif
21532158
};
21542159

21552160
/**

‎src/hotspot/cpu/x86/methodHandles_x86.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -536,10 +536,11 @@ void trace_method_handle_stub(const char* adaptername,
536536
Register r = as_Register(i);
537537
// The registers are stored in reverse order on the stack (by pusha).
538538
#ifdef AMD64
539-
assert(Register::number_of_registers == 16, "sanity");
539+
int num_regs = UseAPX ? 32 : 16;
540+
assert(Register::available_gp_registers() == num_regs, "sanity");
540541
if (r == rsp) {
541542
// rsp is actually not stored by pusha(), compute the old rsp from saved_regs (rsp after pusha): saved_regs + 16 = old rsp
542-
ls.print("%3s=" PTR_FORMAT, r->name(), (intptr_t)(&saved_regs[16]));
543+
ls.print("%3s=" PTR_FORMAT, r->name(), (intptr_t)(&saved_regs[num_regs]));
543544
} else {
544545
ls.print("%3s=" PTR_FORMAT, r->name(), saved_regs[((saved_regs_count - 1) - i)]);
545546
}

‎src/hotspot/cpu/x86/nativeInst_x86.cpp

+23-9
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,13 @@ void NativeCall::set_destination_mt_safe(address dest) {
160160
void NativeMovConstReg::verify() {
161161
#ifdef AMD64
162162
// make sure code pattern is actually a mov reg64, imm64 instruction
163-
if ((ubyte_at(0) != Assembler::REX_W && ubyte_at(0) != Assembler::REX_WB) ||
164-
(ubyte_at(1) & (0xff ^ register_mask)) != 0xB8) {
163+
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
164+
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
165+
(ubyte_at(1) == Assembler::REX2BIT_W ||
166+
ubyte_at(1) == Assembler::REX2BIT_WB ||
167+
ubyte_at(1) == Assembler::REX2BIT_WB4);
168+
int opcode = has_rex2_prefix() ? ubyte_at(2) : ubyte_at(1);
169+
if ((!valid_rex_prefix || !valid_rex2_prefix) && (opcode & (0xff ^ register_mask)) != 0xB8) {
165170
print();
166171
fatal("not a REX.W[B] mov reg64, imm64");
167172
}
@@ -208,6 +213,11 @@ int NativeMovRegMem::instruction_start() const {
208213
instr_0 = ubyte_at(off);
209214
}
210215

216+
if (instr_0 == instruction_REX2_prefix) {
217+
off+=2;
218+
instr_0 = ubyte_at(off);
219+
}
220+
211221
if (instr_0 == instruction_code_xor) {
212222
off += 2;
213223
instr_0 = ubyte_at(off);
@@ -226,29 +236,39 @@ int NativeMovRegMem::instruction_start() const {
226236
instr_0 = ubyte_at(off);
227237
}
228238

239+
if (instr_0 == instruction_REX2_prefix) {
240+
off+=2;
241+
instr_0 = ubyte_at(off);
242+
}
243+
229244
if ( instr_0 >= instruction_prefix_wide_lo && // 0x40
230245
instr_0 <= instruction_prefix_wide_hi) { // 0x4f
231246
off++;
232247
instr_0 = ubyte_at(off);
233248
}
234249

235-
250+
// Extended prefixes can only follow REX prefixes,
251+
// REX2 is directly followed by main opcode.
236252
if (instr_0 == instruction_extended_prefix ) { // 0x0f
237253
off++;
238254
}
239255

256+
// Offset of instruction opcode.
240257
return off;
241258
}
242259

260+
// Format [REX/REX2] [OPCODE] [ModRM] [SIB] [IMM/DISP32]
243261
int NativeMovRegMem::patch_offset() const {
244262
int off = data_offset + instruction_start();
245263
u_char mod_rm = *(u_char*)(instruction_address() + 1);
246264
// nnnn(r12|rsp) isn't coded as simple mod/rm since that is
247265
// the encoding to use an SIB byte. Which will have the nnnn
248266
// field off by one byte
267+
// ModRM Byte Format = Mod[2] REG[3] RM[3]
249268
if ((mod_rm & 7) == 0x4) {
250269
off++;
251270
}
271+
// Displacement offset.
252272
return off;
253273
}
254274

@@ -294,12 +314,6 @@ void NativeMovRegMem::print() {
294314
void NativeLoadAddress::verify() {
295315
// make sure code pattern is actually a mov [reg+offset], reg instruction
296316
u_char test_byte = *(u_char*)instruction_address();
297-
#ifdef _LP64
298-
if ( (test_byte == instruction_prefix_wide ||
299-
test_byte == instruction_prefix_wide_extended) ) {
300-
test_byte = *(u_char*)(instruction_address() + 1);
301-
}
302-
#endif // _LP64
303317
if ( ! ((test_byte == lea_instruction_code)
304318
LP64_ONLY(|| (test_byte == mov64_instruction_code) ))) {
305319
fatal ("not a lea reg, [reg+offs] instruction");

‎src/hotspot/cpu/x86/nativeInst_x86.hpp

+60-18
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class NativeInstruction {
9090
void wrote(int offset);
9191

9292
public:
93+
bool has_rex2_prefix() const { return ubyte_at(0) == Assembler::REX2; }
9394

9495
inline friend NativeInstruction* nativeInstruction_at(address address);
9596
};
@@ -178,48 +179,67 @@ inline NativeCall* nativeCall_before(address return_address) {
178179
return call;
179180
}
180181

182+
// Call with target address in a general purpose register(indirect absolute addressing).
183+
// Encoding : FF /2 CALL r/m32
184+
// Primary Opcode: FF
185+
// Opcode Extension(part of ModRM.REG): /2
186+
// Operand ModRM.RM = r/m32
181187
class NativeCallReg: public NativeInstruction {
182188
public:
183189
enum Intel_specific_constants {
184190
instruction_code = 0xFF,
185191
instruction_offset = 0,
186192
return_address_offset_norex = 2,
187-
return_address_offset_rex = 3
193+
return_address_offset_rex = 3,
194+
return_address_offset_rex2 = 4
188195
};
189196

190197
int next_instruction_offset() const {
191198
if (ubyte_at(0) == NativeCallReg::instruction_code) {
192199
return return_address_offset_norex;
200+
} else if (has_rex2_prefix()) {
201+
return return_address_offset_rex2;
193202
} else {
203+
assert((ubyte_at(0) & 0xF0) == Assembler::REX, "");
194204
return return_address_offset_rex;
195205
}
196206
}
197207
};
198208

199209
// An interface for accessing/manipulating native mov reg, imm32 instructions.
200210
// (used to manipulate inlined 32bit data dll calls, etc.)
211+
// Instruction format for implied addressing mode immediate operand move to register instruction:
212+
// [REX/REX2] [OPCODE] [IMM32]
201213
class NativeMovConstReg: public NativeInstruction {
202214
#ifdef AMD64
203215
static const bool has_rex = true;
204216
static const int rex_size = 1;
217+
static const int rex2_size = 2;
205218
#else
206219
static const bool has_rex = false;
207220
static const int rex_size = 0;
221+
static const int rex2_size = 0;
208222
#endif // AMD64
209223
public:
210224
enum Intel_specific_constants {
211-
instruction_code = 0xB8,
212-
instruction_size = 1 + rex_size + wordSize,
213-
instruction_offset = 0,
214-
data_offset = 1 + rex_size,
215-
next_instruction_offset = instruction_size,
216-
register_mask = 0x07
225+
instruction_code = 0xB8,
226+
instruction_offset = 0,
227+
instruction_size_rex = 1 + rex_size + wordSize,
228+
instruction_size_rex2 = 1 + rex2_size + wordSize,
229+
data_offset_rex = 1 + rex_size,
230+
data_offset_rex2 = 1 + rex2_size,
231+
next_instruction_offset_rex = instruction_size_rex,
232+
next_instruction_offset_rex2 = instruction_size_rex2,
233+
register_mask = 0x07
217234
};
218235

236+
int instruction_size() const { return has_rex2_prefix() ? instruction_size_rex2 : instruction_size_rex; }
237+
int next_inst_offset() const { return has_rex2_prefix() ? next_instruction_offset_rex2 : next_instruction_offset_rex; }
238+
int data_byte_offset() const { return has_rex2_prefix() ? data_offset_rex2 : data_offset_rex;}
219239
address instruction_address() const { return addr_at(instruction_offset); }
220-
address next_instruction_address() const { return addr_at(next_instruction_offset); }
221-
intptr_t data() const { return ptr_at(data_offset); }
222-
void set_data(intptr_t x) { set_ptr_at(data_offset, x); }
240+
address next_instruction_address() const { return addr_at(next_inst_offset()); }
241+
intptr_t data() const { return ptr_at(data_byte_offset()); }
242+
void set_data(intptr_t x) { set_ptr_at(data_byte_offset(), x); }
223243

224244
void verify();
225245
void print();
@@ -238,7 +258,10 @@ inline NativeMovConstReg* nativeMovConstReg_at(address address) {
238258
}
239259

240260
inline NativeMovConstReg* nativeMovConstReg_before(address address) {
241-
NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
261+
int instruction_size = ((NativeInstruction*)(address))->has_rex2_prefix() ?
262+
NativeMovConstReg::instruction_size_rex2 :
263+
NativeMovConstReg::instruction_size_rex;
264+
NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size - NativeMovConstReg::instruction_offset);
242265
#ifdef ASSERT
243266
test->verify();
244267
#endif
@@ -279,35 +302,47 @@ class NativeMovRegMem: public NativeInstruction {
279302
instruction_prefix_wide_hi = Assembler::REX_WRXB,
280303
instruction_code_xor = 0x33,
281304
instruction_extended_prefix = 0x0F,
305+
306+
// Legacy encoding MAP1 instructions promotable to REX2 encoding.
282307
instruction_code_mem2reg_movslq = 0x63,
283308
instruction_code_mem2reg_movzxb = 0xB6,
284309
instruction_code_mem2reg_movsxb = 0xBE,
285310
instruction_code_mem2reg_movzxw = 0xB7,
286311
instruction_code_mem2reg_movsxw = 0xBF,
287312
instruction_operandsize_prefix = 0x66,
313+
314+
// Legacy encoding MAP0 instructions promotable to REX2 encoding.
288315
instruction_code_reg2mem = 0x89,
289316
instruction_code_mem2reg = 0x8b,
290317
instruction_code_reg2memb = 0x88,
291318
instruction_code_mem2regb = 0x8a,
319+
instruction_code_lea = 0x8d,
320+
292321
instruction_code_float_s = 0xd9,
293322
instruction_code_float_d = 0xdd,
294323
instruction_code_long_volatile = 0xdf,
324+
325+
// VEX/EVEX/Legacy encodeded MAP1 instructions promotable to REX2 encoding.
295326
instruction_code_xmm_ss_prefix = 0xf3,
296327
instruction_code_xmm_sd_prefix = 0xf2,
328+
297329
instruction_code_xmm_code = 0x0f,
330+
331+
// Address operand load/store/ldp are promotable to REX2 to accomodate
332+
// extended SIB encoding.
298333
instruction_code_xmm_load = 0x10,
299334
instruction_code_xmm_store = 0x11,
300335
instruction_code_xmm_lpd = 0x12,
301336

302-
instruction_code_lea = 0x8d,
303-
304337
instruction_VEX_prefix_2bytes = Assembler::VEX_2bytes,
305338
instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes,
306339
instruction_EVEX_prefix_4bytes = Assembler::EVEX_4bytes,
340+
instruction_REX2_prefix = Assembler::REX2,
307341

308342
instruction_offset = 0,
309343
data_offset = 2,
310-
next_instruction_offset = 4
344+
next_instruction_offset_rex = 4,
345+
next_instruction_offset_rex2 = 5
311346
};
312347

313348
// helper
@@ -438,7 +473,8 @@ inline NativeJump* nativeJump_at(address address) {
438473
return jump;
439474
}
440475

441-
// Handles all kinds of jump on Intel. Long/far, conditional/unconditional
476+
// Handles all kinds of jump on Intel. Long/far, conditional/unconditional with relative offsets
477+
// barring register indirect jumps.
442478
class NativeGeneralJump: public NativeInstruction {
443479
public:
444480
enum Intel_specific_constants {
@@ -538,7 +574,7 @@ inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) =
538574
inline bool NativeInstruction::is_safepoint_poll() {
539575
#ifdef AMD64
540576
const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
541-
const int test_offset = has_rex_prefix ? 1 : 0;
577+
const int test_offset = has_rex2_prefix() ? 2 : (has_rex_prefix ? 1 : 0);
542578
#else
543579
const int test_offset = 0;
544580
#endif
@@ -549,8 +585,14 @@ inline bool NativeInstruction::is_safepoint_poll() {
549585

550586
inline bool NativeInstruction::is_mov_literal64() {
551587
#ifdef AMD64
552-
return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
553-
(ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
588+
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
589+
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
590+
(ubyte_at(1) == Assembler::REX2BIT_W ||
591+
ubyte_at(1) == Assembler::REX2BIT_WB ||
592+
ubyte_at(1) == Assembler::REX2BIT_WB4);
593+
594+
int opcode = has_rex2_prefix() ? ubyte_at(2) : ubyte_at(1);
595+
return ((valid_rex_prefix || valid_rex2_prefix) && (opcode & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
554596
#else
555597
return false;
556598
#endif // AMD64

‎src/hotspot/cpu/x86/register_x86.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ const char * Register::RegisterImpl::name() const {
3535
static const char *const names[number_of_registers] = {
3636
#ifdef _LP64
3737
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
38-
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
38+
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
39+
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
40+
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
3941
#else
4042
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
4143
#endif // _LP64

‎src/hotspot/cpu/x86/register_x86.hpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class Register {
4545
inline friend constexpr Register as_Register(int encoding);
4646

4747
enum {
48-
number_of_registers = LP64_ONLY( 16 ) NOT_LP64( 8 ),
49-
number_of_byte_registers = LP64_ONLY( 16 ) NOT_LP64( 4 ),
48+
number_of_registers = LP64_ONLY( 32 ) NOT_LP64( 8 ),
49+
number_of_byte_registers = LP64_ONLY( 32 ) NOT_LP64( 4 ),
5050
max_slots_per_register = LP64_ONLY( 2 ) NOT_LP64( 1 )
5151
};
5252

@@ -76,6 +76,16 @@ class Register {
7676
int operator!=(const Register r) const { return _encoding != r._encoding; }
7777

7878
constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; }
79+
80+
// Actually available GP registers for use, depending on actual CPU capabilities and flags.
81+
static int available_gp_registers() {
82+
#ifdef _LP64
83+
if (!UseAPX) {
84+
return number_of_registers / 2;
85+
}
86+
#endif // _LP64
87+
return number_of_registers;
88+
}
7989
};
8090

8191
extern const Register::RegisterImpl all_RegisterImpls[Register::number_of_registers + 1] INTERNAL_VISIBILITY;
@@ -115,6 +125,22 @@ constexpr Register r12 = as_Register(12);
115125
constexpr Register r13 = as_Register(13);
116126
constexpr Register r14 = as_Register(14);
117127
constexpr Register r15 = as_Register(15);
128+
constexpr Register r16 = as_Register(16);
129+
constexpr Register r17 = as_Register(17);
130+
constexpr Register r18 = as_Register(18);
131+
constexpr Register r19 = as_Register(19);
132+
constexpr Register r20 = as_Register(20);
133+
constexpr Register r21 = as_Register(21);
134+
constexpr Register r22 = as_Register(22);
135+
constexpr Register r23 = as_Register(23);
136+
constexpr Register r24 = as_Register(24);
137+
constexpr Register r25 = as_Register(25);
138+
constexpr Register r26 = as_Register(26);
139+
constexpr Register r27 = as_Register(27);
140+
constexpr Register r28 = as_Register(28);
141+
constexpr Register r29 = as_Register(29);
142+
constexpr Register r30 = as_Register(30);
143+
constexpr Register r31 = as_Register(31);
118144
#endif // _LP64
119145

120146

‎src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp

+95-7
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class RegisterSaver {
9595
// units because compiler frame slots are jints.
9696
#define XSAVE_AREA_BEGIN 160
9797
#define XSAVE_AREA_YMM_BEGIN 576
98+
#define XSAVE_AREA_EGPRS 960
9899
#define XSAVE_AREA_OPMASK_BEGIN 1088
99100
#define XSAVE_AREA_ZMM_BEGIN 1152
100101
#define XSAVE_AREA_UPPERBANK 1664
@@ -104,16 +105,33 @@ class RegisterSaver {
104105
#define DEF_OPMASK_OFFS(regnum) opmask ## regnum ## _off = opmask_off + (regnum)*8/BytesPerInt, opmask ## regnum ## H_off
105106
#define DEF_ZMM_UPPER_OFFS(regnum) zmm ## regnum ## _off = zmm_upper_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off
106107
enum layout {
107-
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
108-
xmm_off = fpu_state_off + XSAVE_AREA_BEGIN/BytesPerInt, // offset in fxsave save area
108+
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
109+
xmm_off = fpu_state_off + XSAVE_AREA_BEGIN/BytesPerInt, // offset in fxsave save area
109110
DEF_XMM_OFFS(0),
110111
DEF_XMM_OFFS(1),
111112
// 2..15 are implied in range usage
112113
ymm_off = xmm_off + (XSAVE_AREA_YMM_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt,
113114
DEF_YMM_OFFS(0),
114115
DEF_YMM_OFFS(1),
115116
// 2..15 are implied in range usage
116-
opmask_off = xmm_off + (XSAVE_AREA_OPMASK_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt,
117+
r31_off = xmm_off + (XSAVE_AREA_EGPRS - XSAVE_AREA_BEGIN)/BytesPerInt,
118+
r31H_off,
119+
r30_off, r30H_off,
120+
r29_off, r29H_off,
121+
r28_off, r28H_off,
122+
r27_off, r27H_off,
123+
r26_off, r26H_off,
124+
r25_off, r25H_off,
125+
r24_off, r24H_off,
126+
r23_off, r23H_off,
127+
r22_off, r22H_off,
128+
r21_off, r21H_off,
129+
r20_off, r20H_off,
130+
r19_off, r19H_off,
131+
r18_off, r18H_off,
132+
r17_off, r17H_off,
133+
r16_off, r16H_off,
134+
opmask_off = xmm_off + (XSAVE_AREA_OPMASK_BEGIN - XSAVE_AREA_BEGIN)/BytesPerInt,
117135
DEF_OPMASK_OFFS(0),
118136
DEF_OPMASK_OFFS(1),
119137
// 2..7 are implied in range usage
@@ -199,7 +217,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
199217
// to be under the return like a normal enter.
200218

201219
__ enter(); // rsp becomes 16-byte aligned here
202-
__ push_CPU_state(); // Push a multiple of 16 bytes
220+
__ pushf();
221+
// Make sure rsp stays 16-byte aligned
222+
__ subq(rsp, 8);
223+
// Push CPU state in multiple of 16 bytes
224+
__ save_legacy_gprs();
225+
__ push_FPU_state();
226+
203227

204228
// push cpu state handles this on EVEX enabled targets
205229
if (save_wide_vectors) {
@@ -247,6 +271,17 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
247271
#endif
248272
}
249273
}
274+
275+
#if COMPILER2_OR_JVMCI
276+
if (UseAPX) {
277+
int base_addr = XSAVE_AREA_EGPRS;
278+
off = 0;
279+
for(int n = 16; n < Register::number_of_registers; n++) {
280+
__ movq(Address(rsp, base_addr+(off++*8)), as_Register(n));
281+
}
282+
}
283+
#endif
284+
250285
__ vzeroupper();
251286
if (frame::arg_reg_save_area_bytes != 0) {
252287
// Allocate argument register save area
@@ -279,6 +314,25 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
279314
map->set_callee_saved(STACK_OFFSET( r13_off ), r13->as_VMReg());
280315
map->set_callee_saved(STACK_OFFSET( r14_off ), r14->as_VMReg());
281316
map->set_callee_saved(STACK_OFFSET( r15_off ), r15->as_VMReg());
317+
318+
if (UseAPX) {
319+
map->set_callee_saved(STACK_OFFSET( r16_off ), r16->as_VMReg());
320+
map->set_callee_saved(STACK_OFFSET( r17_off ), r17->as_VMReg());
321+
map->set_callee_saved(STACK_OFFSET( r18_off ), r18->as_VMReg());
322+
map->set_callee_saved(STACK_OFFSET( r19_off ), r19->as_VMReg());
323+
map->set_callee_saved(STACK_OFFSET( r20_off ), r20->as_VMReg());
324+
map->set_callee_saved(STACK_OFFSET( r21_off ), r21->as_VMReg());
325+
map->set_callee_saved(STACK_OFFSET( r22_off ), r22->as_VMReg());
326+
map->set_callee_saved(STACK_OFFSET( r23_off ), r23->as_VMReg());
327+
map->set_callee_saved(STACK_OFFSET( r24_off ), r24->as_VMReg());
328+
map->set_callee_saved(STACK_OFFSET( r25_off ), r25->as_VMReg());
329+
map->set_callee_saved(STACK_OFFSET( r26_off ), r26->as_VMReg());
330+
map->set_callee_saved(STACK_OFFSET( r27_off ), r27->as_VMReg());
331+
map->set_callee_saved(STACK_OFFSET( r28_off ), r28->as_VMReg());
332+
map->set_callee_saved(STACK_OFFSET( r29_off ), r29->as_VMReg());
333+
map->set_callee_saved(STACK_OFFSET( r30_off ), r30->as_VMReg());
334+
map->set_callee_saved(STACK_OFFSET( r31_off ), r31->as_VMReg());
335+
}
282336
// For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
283337
// on EVEX enabled targets, we get it included in the xsave area
284338
off = xmm0_off;
@@ -339,6 +393,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
339393
map->set_callee_saved(STACK_OFFSET( r13H_off ), r13->as_VMReg()->next());
340394
map->set_callee_saved(STACK_OFFSET( r14H_off ), r14->as_VMReg()->next());
341395
map->set_callee_saved(STACK_OFFSET( r15H_off ), r15->as_VMReg()->next());
396+
if (UseAPX) {
397+
map->set_callee_saved(STACK_OFFSET( r16H_off ), r16->as_VMReg()->next());
398+
map->set_callee_saved(STACK_OFFSET( r17H_off ), r17->as_VMReg()->next());
399+
map->set_callee_saved(STACK_OFFSET( r18H_off ), r18->as_VMReg()->next());
400+
map->set_callee_saved(STACK_OFFSET( r19H_off ), r19->as_VMReg()->next());
401+
map->set_callee_saved(STACK_OFFSET( r20H_off ), r20->as_VMReg()->next());
402+
map->set_callee_saved(STACK_OFFSET( r21H_off ), r21->as_VMReg()->next());
403+
map->set_callee_saved(STACK_OFFSET( r22H_off ), r22->as_VMReg()->next());
404+
map->set_callee_saved(STACK_OFFSET( r23H_off ), r23->as_VMReg()->next());
405+
map->set_callee_saved(STACK_OFFSET( r24H_off ), r24->as_VMReg()->next());
406+
map->set_callee_saved(STACK_OFFSET( r25H_off ), r25->as_VMReg()->next());
407+
map->set_callee_saved(STACK_OFFSET( r26H_off ), r26->as_VMReg()->next());
408+
map->set_callee_saved(STACK_OFFSET( r27H_off ), r27->as_VMReg()->next());
409+
map->set_callee_saved(STACK_OFFSET( r28H_off ), r28->as_VMReg()->next());
410+
map->set_callee_saved(STACK_OFFSET( r29H_off ), r29->as_VMReg()->next());
411+
map->set_callee_saved(STACK_OFFSET( r30H_off ), r30->as_VMReg()->next());
412+
map->set_callee_saved(STACK_OFFSET( r31H_off ), r31->as_VMReg()->next());
413+
}
342414
// For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
343415
// on EVEX enabled targets, we get it included in the xsave area
344416
off = xmm0H_off;
@@ -428,8 +500,21 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_wi
428500
}
429501
}
430502

503+
#if COMPILER2_OR_JVMCI
504+
if (UseAPX) {
505+
int base_addr = XSAVE_AREA_EGPRS;
506+
int off = 0;
507+
for (int n = 16; n < Register::number_of_registers; n++) {
508+
__ movq(as_Register(n), Address(rsp, base_addr+(off++*8)));
509+
}
510+
}
511+
#endif
512+
431513
// Recover CPU state
432-
__ pop_CPU_state();
514+
__ pop_FPU_state();
515+
__ restore_legacy_gprs();
516+
__ addq(rsp, 8);
517+
__ popf();
433518
// Get the rbp described implicitly by the calling convention (no oopMap)
434519
__ pop(rbp);
435520
}
@@ -2543,6 +2628,9 @@ void SharedRuntime::generate_deopt_blob() {
25432628
if (UseAVX > 2) {
25442629
pad += 1024;
25452630
}
2631+
if (UseAPX) {
2632+
pad += 1024;
2633+
}
25462634
#if INCLUDE_JVMCI
25472635
if (EnableJVMCI) {
25482636
pad += 512; // Increase the buffer size when compiling for JVMCI
@@ -3091,7 +3179,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
30913179
OopMap* map;
30923180

30933181
// Allocate space for the code. Setup code generation tools.
3094-
CodeBuffer buffer("handler_blob", 2048, 1024);
3182+
CodeBuffer buffer("handler_blob", 2348, 1024);
30953183
MacroAssembler* masm = new MacroAssembler(&buffer);
30963184

30973185
address start = __ pc();
@@ -3247,7 +3335,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
32473335
// allocate space for the code
32483336
ResourceMark rm;
32493337

3250-
CodeBuffer buffer(name, 1200, 512);
3338+
CodeBuffer buffer(name, 1552, 512);
32513339
MacroAssembler* masm = new MacroAssembler(&buffer);
32523340

32533341
int frame_size_in_words;

‎src/hotspot/cpu/x86/upcallLinker_x86_64.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,17 @@
4040
#define __ _masm->
4141

4242
static bool is_valid_XMM(XMMRegister reg) {
43-
return reg->is_valid() && (UseAVX >= 3 || (reg->encoding() < 16)); // why is this not covered by is_valid()?
43+
return reg->is_valid() && (reg->encoding() < (UseAVX >= 3 ? 32 : 16)); // why is this not covered by is_valid()?
44+
}
45+
46+
static bool is_valid_gp(Register reg) {
47+
return reg->is_valid() && (reg->encoding() < (UseAPX ? 32 : 16));
4448
}
4549

4650
// for callee saved regs, according to the caller's ABI
4751
static int compute_reg_save_area_size(const ABIDescriptor& abi) {
4852
int size = 0;
49-
for (Register reg = as_Register(0); reg->is_valid(); reg = reg->successor()) {
53+
for (Register reg = as_Register(0); is_valid_gp(reg); reg = reg->successor()) {
5054
if (reg == rbp || reg == rsp) continue; // saved/restored by prologue/epilogue
5155
if (!abi.is_volatile_reg(reg)) {
5256
size += 8; // bytes
@@ -84,7 +88,7 @@ static void preserve_callee_saved_registers(MacroAssembler* _masm, const ABIDesc
8488
int offset = reg_save_area_offset;
8589

8690
__ block_comment("{ preserve_callee_saved_regs ");
87-
for (Register reg = as_Register(0); reg->is_valid(); reg = reg->successor()) {
91+
for (Register reg = as_Register(0); is_valid_gp(reg); reg = reg->successor()) {
8892
if (reg == rbp || reg == rsp) continue; // saved/restored by prologue/epilogue
8993
if (!abi.is_volatile_reg(reg)) {
9094
__ movptr(Address(rsp, offset), reg);
@@ -134,7 +138,7 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
134138
int offset = reg_save_area_offset;
135139

136140
__ block_comment("{ restore_callee_saved_regs ");
137-
for (Register reg = as_Register(0); reg->is_valid(); reg = reg->successor()) {
141+
for (Register reg = as_Register(0); is_valid_gp(reg); reg = reg->successor()) {
138142
if (reg == rbp || reg == rsp) continue; // saved/restored by prologue/epilogue
139143
if (!abi.is_volatile_reg(reg)) {
140144
__ movptr(reg, Address(rsp, offset));

‎src/hotspot/cpu/x86/vm_version_x86.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
108108

109109
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
110110

111+
#if defined(_LP64)
111112
address clear_apx_test_state() {
112113
# define __ _masm->
113114
address start = __ pc();
114115
// EGPRs are call clobbered registers, Explicit clearing of r16 and r31 during signal
115116
// handling guarantees that preserved register values post signal handling were
116117
// re-instantiated by operating system and not because they were not modified externally.
117118

118-
/* FIXME Uncomment following code after OS enablement of
119119
bool save_apx = UseAPX;
120120
VM_Version::set_apx_cpuFeatures();
121121
UseAPX = true;
@@ -124,10 +124,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
124124
__ mov64(r31, 0L);
125125
UseAPX = save_apx;
126126
VM_Version::clean_cpuFeatures();
127-
*/
128127
__ ret(0);
129128
return start;
130129
}
130+
#endif
131131

132132
address generate_get_cpu_info() {
133133
// Flags to test CPU type.
@@ -419,7 +419,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
419419
__ movl(Address(rsi, 8), rcx);
420420
__ movl(Address(rsi,12), rdx);
421421

422-
#ifndef PRODUCT
422+
#if defined(_LP64)
423423
//
424424
// Check if OS has enabled XGETBV instruction to access XCR0
425425
// (OSXSAVE feature flag) and CPU supports APX
@@ -437,26 +437,22 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
437437
__ cmpl(rax, 0x80000);
438438
__ jcc(Assembler::notEqual, vector_save_restore);
439439

440-
/* FIXME: Uncomment while integrating JDK-8329032
441440
bool save_apx = UseAPX;
442441
VM_Version::set_apx_cpuFeatures();
443442
UseAPX = true;
444443
__ mov64(r16, VM_Version::egpr_test_value());
445444
__ mov64(r31, VM_Version::egpr_test_value());
446-
*/
447445
__ xorl(rsi, rsi);
448446
VM_Version::set_cpuinfo_segv_addr_apx(__ pc());
449447
// Generate SEGV
450448
__ movl(rax, Address(rsi, 0));
451449

452450
VM_Version::set_cpuinfo_cont_addr_apx(__ pc());
453-
/* FIXME: Uncomment after integration of JDK-8329032
454451
__ lea(rsi, Address(rbp, in_bytes(VM_Version::apx_save_offset())));
455452
__ movq(Address(rsi, 0), r16);
456453
__ movq(Address(rsi, 8), r31);
457454

458455
UseAPX = save_apx;
459-
*/
460456
#endif
461457
__ bind(vector_save_restore);
462458
//
@@ -2170,9 +2166,11 @@ int VM_Version::avx3_threshold() {
21702166
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold;
21712167
}
21722168

2169+
#if defined(_LP64)
21732170
void VM_Version::clear_apx_test_state() {
21742171
clear_apx_test_state_stub();
21752172
}
2173+
#endif
21762174

21772175
static bool _vm_version_initialized = false;
21782176

@@ -2191,8 +2189,10 @@ void VM_Version::initialize() {
21912189
detect_virt_stub = CAST_TO_FN_PTR(detect_virt_stub_t,
21922190
g.generate_detect_virt());
21932191

2192+
#if defined(_LP64)
21942193
clear_apx_test_state_stub = CAST_TO_FN_PTR(clear_apx_test_state_t,
21952194
g.clear_apx_test_state());
2195+
#endif
21962196
get_processor_features();
21972197

21982198
LP64_ONLY(Assembler::precompute_instructions();)
@@ -3183,11 +3183,17 @@ bool VM_Version::os_supports_apx_egprs() {
31833183
if (!supports_apx_f()) {
31843184
return false;
31853185
}
3186+
// Enable APX support for product builds after
3187+
// completion of planned features listed in JDK-8329030.
3188+
#if !defined(PRODUCT)
31863189
if (_cpuid_info.apx_save[0] != egpr_test_value() ||
31873190
_cpuid_info.apx_save[1] != egpr_test_value()) {
31883191
return false;
31893192
}
31903193
return true;
3194+
#else
3195+
return false;
3196+
#endif
31913197
}
31923198

31933199
uint VM_Version::cores_per_cpu() {

‎src/hotspot/cpu/x86/vm_version_x86.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ class VM_Version : public Abstract_VM_Version {
635635
static void set_cpuinfo_cont_addr_apx(address pc) { _cpuinfo_cont_addr_apx = pc; }
636636
static address cpuinfo_cont_addr_apx() { return _cpuinfo_cont_addr_apx; }
637637

638-
static void clear_apx_test_state();
638+
LP64_ONLY(static void clear_apx_test_state());
639639

640640
static void clean_cpuFeatures() { _features = 0; }
641641
static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); }

‎src/hotspot/cpu/x86/vmreg_x86.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
#include "register_x86.hpp"
2929

3030
inline bool is_Register() {
31-
return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr;
31+
int uarch_max_gpr = Register::max_slots_per_register * Register::available_gp_registers();
32+
return (unsigned int) value() < (unsigned int) uarch_max_gpr;
3233
}
3334

3435
inline bool is_FloatRegister() {

‎src/hotspot/cpu/x86/x86_64.ad

+115-6
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,53 @@ reg_def R14_H(SOC, SOE, Op_RegI, 14, r14->as_VMReg()->next());
128128
reg_def R15 (SOC, SOE, Op_RegI, 15, r15->as_VMReg());
129129
reg_def R15_H(SOC, SOE, Op_RegI, 15, r15->as_VMReg()->next());
130130

131+
reg_def R16 (SOC, SOC, Op_RegI, 16, r16->as_VMReg());
132+
reg_def R16_H(SOC, SOC, Op_RegI, 16, r16->as_VMReg()->next());
133+
134+
reg_def R17 (SOC, SOC, Op_RegI, 17, r17->as_VMReg());
135+
reg_def R17_H(SOC, SOC, Op_RegI, 17, r17->as_VMReg()->next());
136+
137+
reg_def R18 (SOC, SOC, Op_RegI, 18, r18->as_VMReg());
138+
reg_def R18_H(SOC, SOC, Op_RegI, 18, r18->as_VMReg()->next());
139+
140+
reg_def R19 (SOC, SOC, Op_RegI, 19, r19->as_VMReg());
141+
reg_def R19_H(SOC, SOC, Op_RegI, 19, r19->as_VMReg()->next());
142+
143+
reg_def R20 (SOC, SOC, Op_RegI, 20, r20->as_VMReg());
144+
reg_def R20_H(SOC, SOC, Op_RegI, 20, r20->as_VMReg()->next());
145+
146+
reg_def R21 (SOC, SOC, Op_RegI, 21, r21->as_VMReg());
147+
reg_def R21_H(SOC, SOC, Op_RegI, 21, r21->as_VMReg()->next());
148+
149+
reg_def R22 (SOC, SOC, Op_RegI, 22, r22->as_VMReg());
150+
reg_def R22_H(SOC, SOC, Op_RegI, 22, r22->as_VMReg()->next());
151+
152+
reg_def R23 (SOC, SOC, Op_RegI, 23, r23->as_VMReg());
153+
reg_def R23_H(SOC, SOC, Op_RegI, 23, r23->as_VMReg()->next());
154+
155+
reg_def R24 (SOC, SOC, Op_RegI, 24, r24->as_VMReg());
156+
reg_def R24_H(SOC, SOC, Op_RegI, 24, r24->as_VMReg()->next());
157+
158+
reg_def R25 (SOC, SOC, Op_RegI, 25, r25->as_VMReg());
159+
reg_def R25_H(SOC, SOC, Op_RegI, 25, r25->as_VMReg()->next());
160+
161+
reg_def R26 (SOC, SOC, Op_RegI, 26, r26->as_VMReg());
162+
reg_def R26_H(SOC, SOC, Op_RegI, 26, r26->as_VMReg()->next());
163+
164+
reg_def R27 (SOC, SOC, Op_RegI, 27, r27->as_VMReg());
165+
reg_def R27_H(SOC, SOC, Op_RegI, 27, r27->as_VMReg()->next());
166+
167+
reg_def R28 (SOC, SOC, Op_RegI, 28, r28->as_VMReg());
168+
reg_def R28_H(SOC, SOC, Op_RegI, 28, r28->as_VMReg()->next());
169+
170+
reg_def R29 (SOC, SOC, Op_RegI, 29, r29->as_VMReg());
171+
reg_def R29_H(SOC, SOC, Op_RegI, 29, r29->as_VMReg()->next());
172+
173+
reg_def R30 (SOC, SOC, Op_RegI, 30, r30->as_VMReg());
174+
reg_def R30_H(SOC, SOC, Op_RegI, 30, r30->as_VMReg()->next());
175+
176+
reg_def R31 (SOC, SOC, Op_RegI, 31, r31->as_VMReg());
177+
reg_def R31_H(SOC, SOC, Op_RegI, 31, r31->as_VMReg()->next());
131178

132179
// Floating Point Registers
133180

@@ -154,6 +201,22 @@ alloc_class chunk0(R10, R10_H,
154201
R13, R13_H,
155202
R14, R14_H,
156203
R15, R15_H,
204+
R16, R16_H,
205+
R17, R17_H,
206+
R18, R18_H,
207+
R19, R19_H,
208+
R20, R20_H,
209+
R21, R21_H,
210+
R22, R22_H,
211+
R23, R23_H,
212+
R24, R24_H,
213+
R25, R25_H,
214+
R26, R26_H,
215+
R27, R27_H,
216+
R28, R28_H,
217+
R29, R29_H,
218+
R30, R30_H,
219+
R31, R31_H,
157220
RSP, RSP_H);
158221

159222

@@ -167,7 +230,7 @@ alloc_class chunk0(R10, R10_H,
167230
// Empty register class.
168231
reg_class no_reg();
169232

170-
// Class for all pointer/long registers
233+
// Class for all pointer/long registers including APX extended GPRs.
171234
reg_class all_reg(RAX, RAX_H,
172235
RDX, RDX_H,
173236
RBP, RBP_H,
@@ -183,9 +246,25 @@ reg_class all_reg(RAX, RAX_H,
183246
R12, R12_H,
184247
R13, R13_H,
185248
R14, R14_H,
186-
R15, R15_H);
187-
188-
// Class for all int registers
249+
R15, R15_H,
250+
R16, R16_H,
251+
R17, R17_H,
252+
R18, R18_H,
253+
R19, R19_H,
254+
R20, R20_H,
255+
R21, R21_H,
256+
R22, R22_H,
257+
R23, R23_H,
258+
R24, R24_H,
259+
R25, R25_H,
260+
R26, R26_H,
261+
R27, R27_H,
262+
R28, R28_H,
263+
R29, R29_H,
264+
R30, R30_H,
265+
R31, R31_H);
266+
267+
// Class for all int registers including APX extended GPRs.
189268
reg_class all_int_reg(RAX
190269
RDX,
191270
RBP,
@@ -199,7 +278,23 @@ reg_class all_int_reg(RAX
199278
R11,
200279
R12,
201280
R13,
202-
R14);
281+
R14,
282+
R16,
283+
R17,
284+
R18,
285+
R19,
286+
R20,
287+
R21,
288+
R22,
289+
R23,
290+
R24,
291+
R25,
292+
R26,
293+
R27,
294+
R28,
295+
R29,
296+
R30,
297+
R31);
203298

204299
// Class for all pointer registers
205300
reg_class any_reg %{
@@ -386,6 +481,8 @@ static bool need_r12_heapbase() {
386481
}
387482

388483
void reg_mask_init() {
484+
constexpr Register egprs[] = {r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31};
485+
389486
// _ALL_REG_mask is generated by adlc from the all_reg register class below.
390487
// We derive a number of subsets from it.
391488
_ANY_REG_mask = _ALL_REG_mask;
@@ -404,6 +501,12 @@ void reg_mask_init() {
404501
_PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()->next()));
405502
_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()));
406503
_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()->next()));
504+
if (!UseAPX) {
505+
for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) {
506+
_PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()));
507+
_PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()->next()));
508+
}
509+
}
407510

408511
_STACK_OR_PTR_REG_mask = _PTR_REG_mask;
409512
_STACK_OR_PTR_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
@@ -420,6 +523,7 @@ void reg_mask_init() {
420523
_PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()));
421524
_PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()->next()));
422525

526+
423527
_LONG_REG_mask = _PTR_REG_mask;
424528
_STACK_OR_LONG_REG_mask = _LONG_REG_mask;
425529
_STACK_OR_LONG_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
@@ -441,6 +545,12 @@ void reg_mask_init() {
441545
_LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()->next()));
442546

443547
_INT_REG_mask = _ALL_INT_REG_mask;
548+
if (!UseAPX) {
549+
for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) {
550+
_INT_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()));
551+
}
552+
}
553+
444554
if (PreserveFramePointer) {
445555
_INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
446556
}
@@ -12320,7 +12430,6 @@ instruct safePoint_poll_tls(rFlagsReg cr, rRegP poll)
1232012430
format %{ "testl rax, [$poll]\t"
1232112431
"# Safepoint: poll for GC" %}
1232212432
ins_cost(125);
12323-
size(4); /* setting an explicit size will cause debug builds to assert if size is incorrect */
1232412433
ins_encode %{
1232512434
__ relocate(relocInfo::poll_type);
1232612435
address pre_pc = __ pc();

‎src/hotspot/os/windows/os_windows.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2758,7 +2758,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
27582758
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
27592759
}
27602760

2761-
#ifndef PRODUCT
2761+
#if !defined(PRODUCT) && defined(_LP64)
27622762
if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
27632763
VM_Version::is_cpuinfo_segv_addr_apx(pc)) {
27642764
// Verify that OS save/restore APX registers.

‎src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
416416
stub = VM_Version::cpuinfo_cont_addr();
417417
}
418418

419-
#ifndef PRODUCT
419+
#if !defined(PRODUCT) && defined(_LP64)
420420
if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) {
421421
// Verify that OS save/restore APX registers.
422422
stub = VM_Version::cpuinfo_cont_addr_apx();

‎src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
248248
stub = VM_Version::cpuinfo_cont_addr();
249249
}
250250

251-
#ifndef PRODUCT
251+
#if !defined(PRODUCT) && defined(_LP64)
252252
if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr_apx(pc)) {
253253
// Verify that OS save/restore APX registers.
254254
stub = VM_Version::cpuinfo_cont_addr_apx();

‎src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java

+66-45
Original file line numberDiff line numberDiff line change
@@ -66,49 +66,68 @@ public class AMD64 extends Architecture {
6666
public static final Register r14 = new Register(14, 14, "r14", CPU);
6767
public static final Register r15 = new Register(15, 15, "r15", CPU);
6868

69+
public static final Register r16 = new Register(16, 16, "r16", CPU);
70+
public static final Register r17 = new Register(17, 17, "r17", CPU);
71+
public static final Register r18 = new Register(18, 18, "r18", CPU);
72+
public static final Register r19 = new Register(19, 19, "r19", CPU);
73+
public static final Register r20 = new Register(20, 20, "r20", CPU);
74+
public static final Register r21 = new Register(21, 21, "r21", CPU);
75+
public static final Register r22 = new Register(22, 22, "r22", CPU);
76+
public static final Register r23 = new Register(23, 23, "r23", CPU);
77+
public static final Register r24 = new Register(24, 24, "r24", CPU);
78+
public static final Register r25 = new Register(25, 25, "r25", CPU);
79+
public static final Register r26 = new Register(26, 26, "r26", CPU);
80+
public static final Register r27 = new Register(27, 27, "r27", CPU);
81+
public static final Register r28 = new Register(28, 28, "r28", CPU);
82+
public static final Register r29 = new Register(29, 29, "r29", CPU);
83+
public static final Register r30 = new Register(30, 30, "r30", CPU);
84+
public static final Register r31 = new Register(31, 31, "r31", CPU);
85+
6986
public static final Register[] cpuRegisters = {
7087
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
71-
r8, r9, r10, r11, r12, r13, r14, r15
88+
r8, r9, r10, r11, r12, r13, r14, r15,
89+
r16, r17, r18, r19, r20, r21, r22, r23,
90+
r24, r25, r26, r27, r28, r29, r30, r31
7291
};
7392

7493
public static final RegisterCategory XMM = new RegisterCategory("XMM");
7594

7695
// XMM registers
77-
public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
78-
public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
79-
public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
80-
public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
81-
public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
82-
public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
83-
public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
84-
public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
85-
86-
public static final Register xmm8 = new Register(24, 8, "xmm8", XMM);
87-
public static final Register xmm9 = new Register(25, 9, "xmm9", XMM);
88-
public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
89-
public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
90-
public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
91-
public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
92-
public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
93-
public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
94-
95-
public static final Register xmm16 = new Register(32, 16, "xmm16", XMM);
96-
public static final Register xmm17 = new Register(33, 17, "xmm17", XMM);
97-
public static final Register xmm18 = new Register(34, 18, "xmm18", XMM);
98-
public static final Register xmm19 = new Register(35, 19, "xmm19", XMM);
99-
public static final Register xmm20 = new Register(36, 20, "xmm20", XMM);
100-
public static final Register xmm21 = new Register(37, 21, "xmm21", XMM);
101-
public static final Register xmm22 = new Register(38, 22, "xmm22", XMM);
102-
public static final Register xmm23 = new Register(39, 23, "xmm23", XMM);
103-
104-
public static final Register xmm24 = new Register(40, 24, "xmm24", XMM);
105-
public static final Register xmm25 = new Register(41, 25, "xmm25", XMM);
106-
public static final Register xmm26 = new Register(42, 26, "xmm26", XMM);
107-
public static final Register xmm27 = new Register(43, 27, "xmm27", XMM);
108-
public static final Register xmm28 = new Register(44, 28, "xmm28", XMM);
109-
public static final Register xmm29 = new Register(45, 29, "xmm29", XMM);
110-
public static final Register xmm30 = new Register(46, 30, "xmm30", XMM);
111-
public static final Register xmm31 = new Register(47, 31, "xmm31", XMM);
96+
public static final Register xmm0 = new Register(32, 0, "xmm0", XMM);
97+
public static final Register xmm1 = new Register(33, 1, "xmm1", XMM);
98+
public static final Register xmm2 = new Register(34, 2, "xmm2", XMM);
99+
public static final Register xmm3 = new Register(35, 3, "xmm3", XMM);
100+
public static final Register xmm4 = new Register(36, 4, "xmm4", XMM);
101+
public static final Register xmm5 = new Register(37, 5, "xmm5", XMM);
102+
public static final Register xmm6 = new Register(38, 6, "xmm6", XMM);
103+
public static final Register xmm7 = new Register(39, 7, "xmm7", XMM);
104+
105+
public static final Register xmm8 = new Register(40, 8, "xmm8", XMM);
106+
public static final Register xmm9 = new Register(41, 9, "xmm9", XMM);
107+
public static final Register xmm10 = new Register(42, 10, "xmm10", XMM);
108+
public static final Register xmm11 = new Register(43, 11, "xmm11", XMM);
109+
public static final Register xmm12 = new Register(44, 12, "xmm12", XMM);
110+
public static final Register xmm13 = new Register(45, 13, "xmm13", XMM);
111+
public static final Register xmm14 = new Register(46, 14, "xmm14", XMM);
112+
public static final Register xmm15 = new Register(47, 15, "xmm15", XMM);
113+
114+
public static final Register xmm16 = new Register(48, 16, "xmm16", XMM);
115+
public static final Register xmm17 = new Register(49, 17, "xmm17", XMM);
116+
public static final Register xmm18 = new Register(50, 18, "xmm18", XMM);
117+
public static final Register xmm19 = new Register(51, 19, "xmm19", XMM);
118+
public static final Register xmm20 = new Register(52, 20, "xmm20", XMM);
119+
public static final Register xmm21 = new Register(53, 21, "xmm21", XMM);
120+
public static final Register xmm22 = new Register(54, 22, "xmm22", XMM);
121+
public static final Register xmm23 = new Register(55, 23, "xmm23", XMM);
122+
123+
public static final Register xmm24 = new Register(56, 24, "xmm24", XMM);
124+
public static final Register xmm25 = new Register(57, 25, "xmm25", XMM);
125+
public static final Register xmm26 = new Register(58, 26, "xmm26", XMM);
126+
public static final Register xmm27 = new Register(59, 27, "xmm27", XMM);
127+
public static final Register xmm28 = new Register(60, 28, "xmm28", XMM);
128+
public static final Register xmm29 = new Register(61, 29, "xmm29", XMM);
129+
public static final Register xmm30 = new Register(62, 30, "xmm30", XMM);
130+
public static final Register xmm31 = new Register(63, 31, "xmm31", XMM);
112131

113132
public static final Register[] xmmRegistersSSE = {
114133
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
@@ -124,14 +143,14 @@ public class AMD64 extends Architecture {
124143

125144
public static final RegisterCategory MASK = new RegisterCategory("MASK", false);
126145

127-
public static final Register k0 = new Register(48, 0, "k0", MASK);
128-
public static final Register k1 = new Register(49, 1, "k1", MASK);
129-
public static final Register k2 = new Register(50, 2, "k2", MASK);
130-
public static final Register k3 = new Register(51, 3, "k3", MASK);
131-
public static final Register k4 = new Register(52, 4, "k4", MASK);
132-
public static final Register k5 = new Register(53, 5, "k5", MASK);
133-
public static final Register k6 = new Register(54, 6, "k6", MASK);
134-
public static final Register k7 = new Register(55, 7, "k7", MASK);
146+
public static final Register k0 = new Register(64, 0, "k0", MASK);
147+
public static final Register k1 = new Register(65, 1, "k1", MASK);
148+
public static final Register k2 = new Register(66, 2, "k2", MASK);
149+
public static final Register k3 = new Register(67, 3, "k3", MASK);
150+
public static final Register k4 = new Register(68, 4, "k4", MASK);
151+
public static final Register k5 = new Register(69, 5, "k5", MASK);
152+
public static final Register k6 = new Register(70, 6, "k6", MASK);
153+
public static final Register k7 = new Register(71, 7, "k7", MASK);
135154

136155
public static final RegisterArray valueRegistersSSE = new RegisterArray(
137156
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
@@ -143,6 +162,8 @@ public class AMD64 extends Architecture {
143162
public static final RegisterArray valueRegistersAVX512 = new RegisterArray(
144163
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
145164
r8, r9, r10, r11, r12, r13, r14, r15,
165+
r16, r17, r18, r19, r20, r21, r22, r23,
166+
r24, r25, r26, r27, r28, r29, r30, r31,
146167
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
147168
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
148169
xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
@@ -153,7 +174,7 @@ public class AMD64 extends Architecture {
153174
/**
154175
* Register used to construct an instruction-relative address.
155176
*/
156-
public static final Register rip = new Register(56, -1, "rip", SPECIAL);
177+
public static final Register rip = new Register(72, -1, "rip", SPECIAL);
157178

158179
public static final RegisterArray allRegisters = new RegisterArray(
159180
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,

0 commit comments

Comments
 (0)
Please sign in to comment.