Skip to content

Commit

Permalink
adds unsigned division & modulus intrinsic
Browse files Browse the repository at this point in the history
  • Loading branch information
offamitkumar committed Oct 17, 2024
1 parent 472db92 commit b39788e
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/hotspot/cpu/s390/assembler_s390.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,8 +795,8 @@ class Assembler : public AbstractAssembler {
#define DSGF_ZOPC (unsigned long)(227L << 40 | 29L)
#define DSG_ZOPC (unsigned long)(227L << 40 | 13L)
// RR, unsigned
#define DLR_ZOPC (unsigned int)(185 << 24 | 151 << 16)
#define DLGR_ZOPC (unsigned int)(185 << 24 | 135 << 16)
#define DLR_ZOPC (unsigned int)(0xb997 << 16)
#define DLGR_ZOPC (unsigned int)(0xb987 << 16)
// RM, unsigned
#define DL_ZOPC (unsigned long)(227L << 40 | 151L)
#define DLG_ZOPC (unsigned long)(227L << 40 | 135L)
Expand Down Expand Up @@ -2257,6 +2257,8 @@ class Assembler : public AbstractAssembler {
inline void z_mghi( Register r1, int64_t i2); // mult r1 = r1 * i2_imm16; int64

// Division instructions
inline void z_dlr( Register r1, Register r2); // div r1 = r1 / r2 ; int64/int32 needs reg pair!
inline void z_dlgr( Register r1, Register r2); // div r1 = r1 / r2 ; int128/int64 needs reg pair!
inline void z_dsgr( Register r1, Register r2); // div r1 = r1 / r2 ; int64/int32 needs reg pair!
inline void z_dsgfr(Register r1, Register r2); // div r1 = r1 / r2 ; int64/int32 needs reg pair!

Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/s390/assembler_s390.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,8 @@ inline void Assembler::z_mghi( Register r1, int64_t i2) { emit_32( MGHI_ZOPC |
//------------------
// DIVIDE
//------------------
inline void Assembler::z_dlr( Register r1, Register r2) { emit_32( DLR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }
inline void Assembler::z_dlgr( Register r1, Register r2) { emit_32( DLGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }
inline void Assembler::z_dsgr( Register r1, Register r2) { emit_32( DSGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }
inline void Assembler::z_dsgfr(Register r1, Register r2) { emit_32( DSGFR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }

Expand Down
95 changes: 95 additions & 0 deletions src/hotspot/cpu/s390/s390.ad
Original file line number Diff line number Diff line change
Expand Up @@ -6253,6 +6253,29 @@ instruct divI_reg_imm16(roddRegI dst, iRegI src1, immI16 src2, revenRegI tmp, fl
ins_pipe(pipe_class_dummy);
%}

// Unsigned Integer Register Division
// NOTE: z_dlr requires even-odd pair. remainder will be in even register(r4) & quotient will be stored in odd register(r5)
// for dividend, leftmost 32bits will be in r4 and rightmost 32bits will be in r5 register.
instruct udivI_reg_reg(roddRegI r5_rodd_dst, iRegI src2, revenRegI r4_reven_tmp, flagsReg cr) %{
match(Set r5_rodd_dst (UDivI r5_rodd_dst src2));
effect(TEMP r4_reven_tmp, KILL cr);
// TODO: size(4);
format %{ "UDIV $r5_rodd_dst, $r5_rodd_dst,$src2" %}
ins_encode %{
Register b = $src2$$Register;
Register r4_reven_tmp = $r4_reven_tmp$$Register;
Register r5_rodd_dst = $r5_rodd_dst$$Register;
assert_different_registers(r4_reven_tmp, r5_rodd_dst, b);
assert(r4_reven_tmp->successor() == r5_rodd_dst, "even-odd pair required for the instruction");

__ block_comment("unsigned_div_int {");
__ z_lhi(r4_reven_tmp, 0); // make leftmost 32bits 0
__ z_dlr(r4_reven_tmp, b);
__ block_comment("} unsigned_div_int");
%}
ins_pipe(pipe_class_dummy);
%}

// Long DIVMOD with Register, both quotient and mod results
instruct divModL_reg_divmod(roddRegL dst1src1, revenRegL dst2, iRegL src2, flagsReg cr) %{
match(DivModL dst1src1 src2);
Expand Down Expand Up @@ -6309,6 +6332,28 @@ instruct divL_reg_reg(roddRegL dst, iRegL src, revenRegL tmp, flagsReg cr) %{
ins_pipe(pipe_class_dummy);
%}

// Register Unsigned Long Division
// NOTE: z_dlgr requires even-odd pair. remainder will be in even register(r4) & quotient will be stored in odd register(r5)
// for dividend, leftmost 64bits will be in r4 and rightmost 64bits will be in r5 register.
instruct udivL_reg_reg(roddRegL r5_rodd_dst, iRegL src, revenRegL r4_reven_tmp, flagsReg cr) %{
match(Set r5_rodd_dst (UDivL r5_rodd_dst src));
effect(TEMP r4_reven_tmp, KILL cr);
ins_cost(DEFAULT_COST);
// TODO: size(4);
format %{ "UDIVG $r5_rodd_dst, $r5_rodd_dst, $src" %}
ins_encode %{
Register b = $src$$Register;
Register r5_rodd_dst = $r5_rodd_dst$$Register;
Register r4_reven_tmp = $r4_reven_tmp$$Register;
assert_different_registers(r5_rodd_dst, r4_reven_tmp, b);
__ block_comment("unsigned_div_long {");
__ z_lghi(r4_reven_tmp, 0); // make leftmost 64bits 0
__ z_dlgr(r4_reven_tmp, b);
__ block_comment("} unsigned_div_long");
%}
ins_pipe(pipe_class_dummy);
%}

// Immediate Long Division
instruct divL_reg_imm16(roddRegL dst, iRegL src1, immL16 src2, revenRegL tmp, flagsReg cr) %{
match(Set dst (DivL src1 src2));
Expand Down Expand Up @@ -6374,6 +6419,31 @@ instruct modI_reg_reg(revenRegI dst, iRegI src1, noOdd_iRegI src2, roddRegI tmp,
ins_pipe(pipe_class_dummy);
%}

// Register Unsigned Integer Remainder
// NOTE: z_dlr requires even-odd pair. remainder will be in even register(r4) & quotient will be stored in odd register(r5)
// for dividend, leftmost 32bits will be in r4 and rightmost 32bits will be in r5 register.
instruct umodI_reg_reg(revenRegI r4_reven_dst, iRegI src2, roddRegI r5_rodd_tmp, flagsReg cr) %{
match(Set r4_reven_dst (UModI r4_reven_dst src2));
effect(TEMP r5_rodd_tmp, KILL cr);
ins_cost(DEFAULT_COST);
// TODO: s390 port size(VARIABLE_SIZE);
format %{ "UMOD $r4_reven_dst,$r4_reven_dst,$src2" %}
ins_encode %{
Register b = $src2$$Register;
Register r4_reven_dst = $r4_reven_dst$$Register;
Register r5_rodd_tmp = $r5_rodd_tmp$$Register;
assert_different_registers(r4_reven_dst, r5_rodd_tmp, b);
assert(r4_reven_dst->successor() == r5_rodd_tmp, "must be an even-odd pair");

__ block_comment("unsigned_mod_integer {");
__ z_lr(r5_rodd_tmp, r4_reven_dst); // load rightmost 32bits in odd register
__ z_lhi(r4_reven_dst, 0); // make leftmost 32bits 0
__ z_dlr(r4_reven_dst, b);
__ block_comment("} unsigned_mod_integer");
%}
ins_pipe(pipe_class_dummy);
%}

// Immediate Remainder
instruct modI_reg_imm16(revenRegI dst, iRegI src1, immI16 src2, roddRegI tmp, flagsReg cr) %{
match(Set dst (ModI src1 src2));
Expand Down Expand Up @@ -6437,6 +6507,31 @@ instruct modL_reg_reg(revenRegL dst, roddRegL src1, iRegL src2, flagsReg cr) %{
ins_pipe(pipe_class_dummy);
%}

// Register Unsigned Long Remainder
// NOTE: z_dlgr requires even-odd pair. remainder will be in even register(r4) & quotient will be stored in odd register(r5)
// for dividend, leftmost 64bits will be in r4 and rightmost 64bits will be in r5 register.
instruct umodL_reg_reg(revenRegL r4_reven_dst, roddRegL r5_rodd_tmp, iRegL src2, flagsReg cr) %{
match(Set r4_reven_dst (UModL r4_reven_dst src2));
effect(TEMP r5_rodd_tmp, KILL cr);
ins_cost(DEFAULT_COST);
// TODO: s390 port size(VARIABLE_SIZE);
format %{ "UMODG $r4_reven_dst,$r4_reven_dst,$src2" %}
ins_encode %{
Register b = $src2$$Register;
Register r4_reven_dst = $r4_reven_dst$$Register;
Register r5_rodd_tmp = $r5_rodd_tmp$$Register;
assert_different_registers(r4_reven_dst, r5_rodd_tmp, b);
assert(r4_reven_dst->successor() == r5_rodd_tmp, "instruction requires an even-odd pair" );

__ block_comment("unsigned_mod_long {");
__ z_lgr(r5_rodd_tmp, r4_reven_dst); // load rightmost 64bits in even register
__ z_lghi(r4_reven_dst, 0); // make leftmost 64bits 0
__ z_dlgr(r4_reven_dst, b);
__ block_comment("} unsigned_mod_long");
%}
ins_pipe(pipe_class_dummy);
%}

// Register Long Remainder
instruct modL_reg_imm16(revenRegL dst, iRegL src1, immL16 src2, roddRegL tmp, flagsReg cr) %{
match(Set dst (ModL src1 src2));
Expand Down

0 comments on commit b39788e

Please sign in to comment.