Skip to content

Commit

Permalink
Implement operations on s390x
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoltan Herczeg committed Apr 17, 2023
1 parent c54325f commit 7f28861
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 5 deletions.
101 changes: 99 additions & 2 deletions sljit_src/sljitNativeS390X.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
}
/* fallthrough */

case SLJIT_ATOMIC_STORED:
case SLJIT_F_EQUAL:
case SLJIT_ORDERED_EQUAL:
return cc0;
Expand All @@ -230,6 +231,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
return (cc1 | cc2 | cc3);

case SLJIT_LESS:
case SLJIT_ATOMIC_NOT_STORED:
return cc1;

case SLJIT_GREATER_EQUAL:
Expand Down Expand Up @@ -1749,7 +1751,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;
compiler->local_size = local_size;

FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
if (is_s20(-local_size))
FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
else
FAIL_IF(push_inst(compiler, 0xc20400000000 /* slgfi */ | R36A(r15) | (sljit_ins)local_size));

if (options & SLJIT_ENTER_REG_ARG)
return SLJIT_SUCCESS;
Expand Down Expand Up @@ -1794,8 +1799,10 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit

if (is_u12(local_size))
FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size));
else
else if (is_s20(local_size))
FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size)));
else
FAIL_IF(push_inst(compiler, 0xc20a00000000 /* algfi */ | R36A(r15) | (sljit_ins)local_size));

offset = 2 * SSIZE_OF(sw);
if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {
Expand Down Expand Up @@ -3449,6 +3456,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
return SLJIT_SUCCESS;
}

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f32 value)
{
union {
sljit_s32 imm;
sljit_f32 value;
} u;

CHECK_ERROR();
CHECK(check_sljit_emit_fset32(compiler, freg, value));

u.value = value;

FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)u.imm << 32));
return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));
}

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_sw imm;
sljit_f64 value;
} u;

CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));

u.value = value;

FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)u.imm));
return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));
}

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
Expand Down Expand Up @@ -3840,6 +3881,62 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw)));
}

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst_reg,
sljit_s32 mem_reg)
{
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));

SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_op1(compiler, op, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);
}

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src_reg,
sljit_s32 mem_reg,
sljit_s32 temp_reg)
{
sljit_ins mask;
sljit_gpr tmp_r = gpr(temp_reg);
sljit_gpr mem_r = gpr(mem_reg);

CHECK_ERROR();
CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));

switch (GET_OPCODE(op)) {
case SLJIT_MOV32:
case SLJIT_MOV_U32:
return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r));
case SLJIT_MOV_U8:
mask = 0xff;
break;
case SLJIT_MOV_U16:
mask = 0xffff;
break;
default:
return push_inst(compiler, 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r));
}

/* tmp0 = (src_reg ^ tmp_r) & mask */
FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | mask));
FAIL_IF(push_inst(compiler, 0xb9e70000 /* xgrk */ | R4A(tmp0) | R0A(gpr(src_reg)) | R12A(tmp_r)));
FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(tmp_r) | 0xfffc));
FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp0) | R0A(tmp1)));

/* tmp0 = tmp0 << (((mem_r ^ 0x3) & 0x3) << 3) */
FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | (sljit_ins)((mask == 0xff) ? 0x18 : 0x10)));
FAIL_IF(push_inst(compiler, 0xb9800000 /* ngr */ | R4A(tmp_r) | R0A(mem_r)));
FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp1) | R32A(mem_r) | (58 << 24) | (60 << 16) | (3 << 8)));
FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(tmp0) | R28A(tmp1)));

/* Already computed: tmp_r = mem_r & ~0x3 */

FAIL_IF(push_inst(compiler, 0x58000000 /* l */ | R20A(tmp1) | R12A(tmp_r)));
FAIL_IF(push_inst(compiler, 0x1700 /* x */ | R4A(tmp0) | R0A(tmp1)));
return push_inst(compiler, 0xba000000 /* cs */ | R20A(tmp1) | R16A(tmp0) | R12A(tmp_r));
}

/* --------------------------------------------------------------------- */
/* Other instructions */
/* --------------------------------------------------------------------- */
Expand Down
53 changes: 50 additions & 3 deletions test_src/sljitTest.c
Original file line number Diff line number Diff line change
Expand Up @@ -11523,21 +11523,22 @@ static void test91(void)
static void test92(void)
{
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
|| (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/* Test atomic load and store. */
executable_code code;
struct sljit_compiler *compiler = sljit_create_compiler(NULL, NULL);
struct sljit_label *label;
struct sljit_jump *jump;
sljit_sw buf[26];
sljit_sw buf[32];
sljit_s32 i;

if (verbose)
printf("Run test92\n");

FAILED(!compiler, "cannot create compiler\n");

for (i = 0; i < 26; i++)
for (i = 0; i < 32; i++)
buf[i] = -1;

buf[0] = -4678;
Expand All @@ -11549,6 +11550,9 @@ static void test92(void)
*(sljit_u32*)(buf + 17) = 987609876;
*(sljit_u8*)(buf + 20) = 192;
buf[23] = 6359;
((sljit_u8*)(buf + 26))[1] = 105;
((sljit_u8*)(buf + 28))[2] = 13;
((sljit_u16*)(buf + 30))[1] = 14876;

sljit_emit_enter(compiler, 0, SLJIT_ARGS1(VOID, P), 5, 5, 0, 0, 2 * sizeof(sljit_sw));

Expand Down Expand Up @@ -11671,6 +11675,38 @@ static void test92(void)
/* buf[25] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 25 * sizeof(sljit_sw), SLJIT_R0, 0);

sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 26 * sizeof(sljit_sw) + 1);
label = sljit_emit_label(compiler);
sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R0, SLJIT_R1);
/* buf[27] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 27 * sizeof(sljit_sw), SLJIT_R0, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 204);
/* buf[26] */
sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);
jump = sljit_emit_jump(compiler, SLJIT_ATOMIC_STORED);
sljit_set_label(sljit_emit_jump(compiler, SLJIT_JUMP), label);
sljit_set_label(jump, sljit_emit_label(compiler));

sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 28 * sizeof(sljit_sw) + 2);
label = sljit_emit_label(compiler);
sljit_emit_atomic_load(compiler, SLJIT_MOV_U8, SLJIT_R0, SLJIT_R1);
/* buf[29] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 29 * sizeof(sljit_sw), SLJIT_R0, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 240);
/* buf[28] */
sljit_emit_atomic_store(compiler, SLJIT_MOV_U8 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);
sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);

sljit_emit_op2(compiler, SLJIT_ADD, SLJIT_R1, 0, SLJIT_S0, 0, SLJIT_IMM, 30 * sizeof(sljit_sw) + 2);
label = sljit_emit_label(compiler);
sljit_emit_atomic_load(compiler, SLJIT_MOV_U16, SLJIT_R0, SLJIT_R1);
/* buf[31] */
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_S0), 31 * sizeof(sljit_sw), SLJIT_R0, 0);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, 51403);
/* buf[30] */
sljit_emit_atomic_store(compiler, SLJIT_MOV_U16 | SLJIT_SET_ATOMIC_STORED, SLJIT_R2, SLJIT_R1, SLJIT_R0);
sljit_set_label(sljit_emit_jump(compiler, SLJIT_ATOMIC_NOT_STORED), label);

sljit_emit_return_void(compiler);

code.code = sljit_generate_code(compiler);
Expand Down Expand Up @@ -11715,6 +11751,17 @@ static void test92(void)
FAILED(buf[23] != 4059, "test92 case 31 failed\n");
FAILED(buf[24] != 6359, "test92 case 32 failed\n");
FAILED(buf[25] != (sljit_sw)(buf + 23), "test92 case 33 failed\n");
FAILED(((sljit_u8*)(buf + 26))[0] != 255, "test92 case 34 failed\n");
FAILED(((sljit_u8*)(buf + 26))[1] != 204, "test92 case 35 failed\n");
FAILED(((sljit_u8*)(buf + 26))[2] != 255, "test92 case 36 failed\n");
FAILED(buf[27] != 105, "test92 case 37 failed\n");
FAILED(((sljit_u8*)(buf + 28))[1] != 255, "test92 case 38 failed\n");
FAILED(((sljit_u8*)(buf + 28))[2] != 240, "test92 case 39 failed\n");
FAILED(((sljit_u8*)(buf + 28))[3] != 255, "test92 case 40 failed\n");
FAILED(buf[29] != 13, "test92 case 41 failed\n");
FAILED(((sljit_u16*)(buf + 30))[0] != 65535, "test92 case 42 failed\n");
FAILED(((sljit_u16*)(buf + 30))[1] != 51403, "test92 case 43 failed\n");
FAILED(buf[31] != 14876, "test92 case 44 failed\n");

sljit_free_code(code.code, NULL);
#endif
Expand Down

0 comments on commit 7f28861

Please sign in to comment.