@@ -778,14 +778,12 @@ static void* dasm_labels[zend_lb_MAX];
778
778
779
779
// Define GET_ZVAL_DVAL to replace SSE_GET_ZVAL_DVAL in x86 implementation.
780
780
|.macro GET_ZVAL_DVAL, reg, addr, tmp_reg
781
- | brk #0 // TODO: test
782
781
|| if (Z_MODE(addr) != IS_REG || reg != Z_REG(addr)) {
783
782
|| if (Z_MODE(addr) == IS_CONST_ZVAL) {
784
783
| brk #0 // TODO: test
785
784
| LOAD_ADDR Rx(tmp_reg), Z_ZV(addr)
786
785
| ldr Rd(reg-ZREG_V0), [Rx(tmp_reg)]
787
786
|| } else if (Z_MODE(addr) == IS_MEM_ZVAL) {
788
- | brk #0 // TODO: test
789
787
| SAFE_MEM_ACC_WITH_UOFFSET ldr, Rd(reg-ZREG_V0), Rx(Z_REG(addr)), Z_OFFSET(addr), Rx(tmp_reg)
790
788
|| } else if (Z_MODE(addr) == IS_REG) {
791
789
| brk #0 // TODO: test
@@ -4377,10 +4375,20 @@ static int zend_jit_cmp_double_common(dasm_State **Dst, const zend_op *opline, z
4377
4375
case ZEND_IS_IDENTICAL:
4378
4376
case ZEND_CASE:
4379
4377
case ZEND_CASE_STRICT:
4380
- | brk #0 // TODO
4378
+ if (exit_addr) {
4379
+ | brk #0 // TODO
4380
+ } else {
4381
+ | bne => target_label
4382
+ }
4381
4383
break;
4382
4384
case ZEND_IS_NOT_EQUAL:
4383
- | brk #0 // TODO
4385
+ | bvs >1
4386
+ if (exit_addr) {
4387
+ | brk #0 // TODO
4388
+ } else {
4389
+ | beq => target_label
4390
+ }
4391
+ |1:
4384
4392
break;
4385
4393
case ZEND_IS_NOT_IDENTICAL:
4386
4394
| brk #0 // TODO
@@ -4421,13 +4429,171 @@ static int zend_jit_cmp_double_common(dasm_State **Dst, const zend_op *opline, z
4421
4429
ZEND_UNREACHABLE();
4422
4430
}
4423
4431
} else if (smart_branch_opcode == ZEND_JMPNZ) {
4424
- | brk #0 // TODO
4432
+ switch (opline->opcode) {
4433
+ case ZEND_IS_EQUAL:
4434
+ case ZEND_IS_IDENTICAL:
4435
+ case ZEND_CASE:
4436
+ case ZEND_CASE_STRICT:
4437
+ | bvs >1
4438
+ if (exit_addr) {
4439
+ | brk #0 // TODO
4440
+ } else {
4441
+ | beq => target_label
4442
+ }
4443
+ |1:
4444
+ break;
4445
+ case ZEND_IS_NOT_EQUAL:
4446
+ if (exit_addr) {
4447
+ | brk #0 // TODO
4448
+ } else {
4449
+ | bne => target_label
4450
+ }
4451
+ break;
4452
+ case ZEND_IS_NOT_IDENTICAL:
4453
+ | brk #0 // TODO
4454
+ break;
4455
+ case ZEND_IS_SMALLER:
4456
+ if (swap) {
4457
+ if (exit_addr) {
4458
+ | brk #0 // TODO
4459
+ } else {
4460
+ | bvs >1 // Always False if involving NaN
4461
+ | bhi => target_label
4462
+ |1:
4463
+ }
4464
+ } else {
4465
+ | bvs >1
4466
+ if (exit_addr) {
4467
+ | brk #0 // TODO
4468
+ } else {
4469
+ | blo => target_label
4470
+ }
4471
+ |1:
4472
+ }
4473
+ break;
4474
+ case ZEND_IS_SMALLER_OR_EQUAL:
4475
+ if (swap) {
4476
+ if (exit_addr) {
4477
+ | brk #0 // TODO
4478
+ } else {
4479
+ | bvs >1 // Always False if involving NaN
4480
+ | bhs => target_label
4481
+ |1:
4482
+ }
4483
+ } else {
4484
+ | bvs >1
4485
+ if (exit_addr) {
4486
+ | brk #0 // TODO
4487
+ } else {
4488
+ | bls => target_label
4489
+ }
4490
+ |1:
4491
+ }
4492
+ break;
4493
+ default:
4494
+ ZEND_UNREACHABLE();
4495
+ }
4425
4496
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
4426
4497
| brk #0 // TODO
4427
4498
} else if (smart_branch_opcode == ZEND_JMPZ_EX) {
4428
- | brk #0 // TODO
4499
+ switch (opline->opcode) {
4500
+ case ZEND_IS_EQUAL:
4501
+ case ZEND_IS_IDENTICAL:
4502
+ case ZEND_CASE:
4503
+ case ZEND_CASE_STRICT:
4504
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4505
+ | bne => target_label
4506
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4507
+ break;
4508
+ case ZEND_IS_NOT_EQUAL:
4509
+ case ZEND_IS_NOT_IDENTICAL:
4510
+ | bvs >1
4511
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4512
+ | beq => target_label
4513
+ |1:
4514
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4515
+ break;
4516
+ case ZEND_IS_SMALLER:
4517
+ if (swap) {
4518
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4519
+ | bvs => target_label // TODO: why the NaN check is missing in x86?
4520
+ | bls => target_label
4521
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4522
+ } else {
4523
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4524
+ | bhs => target_label
4525
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4526
+ }
4527
+ break;
4528
+ case ZEND_IS_SMALLER_OR_EQUAL:
4529
+ if (swap) {
4530
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4531
+ | bvs => target_label // TODO: why the NaN check is missing in x86?
4532
+ | blo => target_label
4533
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4534
+ } else {
4535
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4536
+ | bhi => target_label
4537
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4538
+ }
4539
+ break;
4540
+ default:
4541
+ ZEND_UNREACHABLE();
4542
+ }
4429
4543
} else if (smart_branch_opcode == ZEND_JMPNZ_EX) {
4430
- | brk #0 // TODO
4544
+ switch (opline->opcode) {
4545
+ case ZEND_IS_EQUAL:
4546
+ case ZEND_IS_IDENTICAL:
4547
+ case ZEND_CASE:
4548
+ case ZEND_CASE_STRICT:
4549
+ | bvs >1
4550
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4551
+ | beq => target_label
4552
+ |1:
4553
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4554
+ break;
4555
+ case ZEND_IS_NOT_EQUAL:
4556
+ case ZEND_IS_NOT_IDENTICAL:
4557
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4558
+ | bvs => target_label
4559
+ | bne => target_label
4560
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4561
+ break;
4562
+ case ZEND_IS_SMALLER:
4563
+ if (swap) {
4564
+ | cset REG0w, hi
4565
+ | add REG0w, REG0w, #2
4566
+ | SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
4567
+ | bvs >1 // Always False if involving NaN
4568
+ | bhi => target_label
4569
+ |1:
4570
+ } else {
4571
+ | bvs >1
4572
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4573
+ | blo => target_label
4574
+ |1:
4575
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4576
+ }
4577
+ break;
4578
+ case ZEND_IS_SMALLER_OR_EQUAL:
4579
+ if (swap) {
4580
+ | cset REG0w, hs
4581
+ | add REG0w, REG0w, #2
4582
+ | SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
4583
+ | bvs >1 // Always False if involving NaN
4584
+ | bhs => target_label
4585
+ |1:
4586
+ } else {
4587
+ | bvs >1
4588
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE, TMP1w, TMP2
4589
+ | bls => target_label
4590
+ |1:
4591
+ | SET_ZVAL_TYPE_INFO res_addr, IS_FALSE, TMP1w, TMP2
4592
+ }
4593
+ break;
4594
+ default:
4595
+ ZEND_UNREACHABLE();
4596
+ }
4431
4597
} else {
4432
4598
ZEND_UNREACHABLE();
4433
4599
}
@@ -4437,11 +4603,22 @@ static int zend_jit_cmp_double_common(dasm_State **Dst, const zend_op *opline, z
4437
4603
case ZEND_IS_IDENTICAL:
4438
4604
case ZEND_CASE:
4439
4605
case ZEND_CASE_STRICT:
4440
- | brk #0 // TODO
4606
+ | bvs >1
4607
+ | mov REG0, #IS_TRUE
4608
+ | beq >2
4609
+ |1:
4610
+ | mov REG0, #IS_FALSE
4611
+ |2:
4441
4612
break;
4442
4613
case ZEND_IS_NOT_EQUAL:
4443
4614
case ZEND_IS_NOT_IDENTICAL:
4444
- | brk #0 // TODO
4615
+ | bvs >1
4616
+ | mov REG0, #IS_FALSE
4617
+ | beq >2
4618
+ |1:
4619
+ | mov REG0, #IS_TRUE
4620
+ |2:
4621
+ break;
4445
4622
break;
4446
4623
case ZEND_IS_SMALLER:
4447
4624
| bvs >1
@@ -4500,7 +4677,19 @@ static int zend_jit_cmp_double_double(dasm_State **Dst, const zend_op *opline, z
4500
4677
{
4501
4678
bool swap = 0;
4502
4679
4503
- | brk #0 // TODO
4680
+ if (Z_MODE(op1_addr) == IS_REG) {
4681
+ | brk #0 // TODO
4682
+ | DOUBLE_CMP fcmp, Z_REG(op1_addr), op2_addr, ZREG_TMP1, ZREG_FPTMP
4683
+ } else if (Z_MODE(op2_addr) == IS_REG) {
4684
+ | brk #0 // TODO: construct test cases to verify whether the missing NaN check in x86 is buggy or not.
4685
+ | DOUBLE_CMP fcmp, Z_REG(op2_addr), op1_addr, ZREG_TMP1, ZREG_FPTMP
4686
+ swap = 1;
4687
+ } else {
4688
+ zend_reg tmp_reg = ZREG_FPR0;
4689
+
4690
+ | GET_ZVAL_DVAL tmp_reg, op1_addr, ZREG_TMP1
4691
+ | DOUBLE_CMP fcmp, tmp_reg, op2_addr, ZREG_TMP1, ZREG_FPTMP
4692
+ }
4504
4693
4505
4694
return zend_jit_cmp_double_common(Dst, opline, res_addr, swap, smart_branch_opcode, target_label, target_label2, exit_addr);
4506
4695
}
@@ -4580,7 +4769,6 @@ static int zend_jit_cmp(dasm_State **Dst,
4580
4769
| IF_NOT_ZVAL_TYPE op2_addr, IS_DOUBLE, >9, TMP1w, TMP2
4581
4770
}
4582
4771
}
4583
- | brk #0 // TODO
4584
4772
if (!zend_jit_cmp_double_double(Dst, opline, op1_addr, op2_addr, res_addr, smart_branch_opcode, target_label, target_label2, exit_addr)) {
4585
4773
return 0;
4586
4774
}
@@ -4693,7 +4881,8 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_
4693
4881
}
4694
4882
4695
4883
if (op1_info & MAY_BE_REF) {
4696
- | brk #0 // TODO
4884
+ | LOAD_ZVAL_ADDR FCARG1x, op1_addr
4885
+ | ZVAL_DEREF FCARG1x, op1_info, TMP1w
4697
4886
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1x, 0);
4698
4887
}
4699
4888
@@ -4710,7 +4899,20 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_
4710
4899
} else {
4711
4900
| CMP_ZVAL_TYPE op1_addr, IS_TRUE, TMP1w, TMP2
4712
4901
if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE))) {
4713
- | brk #0 // TODO
4902
+ if ((op1_info & MAY_BE_LONG) &&
4903
+ !(op1_info & MAY_BE_UNDEF) &&
4904
+ !set_bool) {
4905
+ if (exit_addr) {
4906
+ | brk #0 // TODO
4907
+ } else if (false_label != (uint32_t)-1) {
4908
+ | brk #0 // TODO
4909
+ } else {
4910
+ | brk #0 // TODO
4911
+ }
4912
+ jmp_done = 1;
4913
+ } else {
4914
+ | bgt >2
4915
+ }
4714
4916
}
4715
4917
if (!(op1_info & MAY_BE_TRUE)) {
4716
4918
/* It's FALSE */
@@ -4732,23 +4934,82 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_
4732
4934
}
4733
4935
}
4734
4936
} else if (set_bool) {
4735
- | brk #0 // TODO
4937
+ | cset REG0w, eq
4938
+ if (set_bool_not) {
4939
+ | brk #0 // TODO
4940
+ | neg REG0w, REG0w
4941
+ | add REG0w, REG0w, #3
4942
+ } else {
4943
+ | add REG0w, REG0w, #2
4944
+ }
4945
+ if ((op1_info & MAY_BE_UNDEF) && (op1_info & MAY_BE_ANY)) {
4946
+ set_delayed = 1;
4947
+ } else {
4948
+ | brk #0 // TODO
4949
+ | SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
4950
+ }
4736
4951
}
4737
4952
}
4738
4953
}
4739
4954
4740
4955
/* It's FALSE, but may be UNDEF */
4741
4956
if (op1_info & MAY_BE_UNDEF) {
4957
+ if (op1_info & MAY_BE_ANY) {
4958
+ if (set_delayed) {
4959
+ | CMP_ZVAL_TYPE op1_addr, IS_UNDEF, TMP1w, TMP2
4960
+ | SET_ZVAL_TYPE_INFO_FROM_REG res_addr, REG0w, TMP1
4961
+ | beq >1
4962
+ } else {
4963
+ | brk #0 // TODO
4964
+ | IF_ZVAL_TYPE op1_addr, IS_UNDEF, >1, TMP1w, TMP2
4965
+ }
4966
+ |.cold_code
4967
+ |1:
4968
+ }
4742
4969
| brk #0 // TODO
4970
+ | LOAD_32BIT_VAL FCARG1w, opline->op1.var
4971
+ | SET_EX_OPLINE opline, REG0
4972
+ | EXT_CALL zend_jit_undefined_op_helper, REG0
4973
+
4974
+ if (may_throw) {
4975
+ if (!zend_jit_check_exception_undef_result(Dst, opline)) {
4976
+ return 0;
4977
+ }
4978
+ }
4979
+
4980
+ if (exit_addr) {
4981
+ if (branch_opcode == ZEND_JMPZ || branch_opcode == ZEND_JMPZ_EX) {
4982
+ | brk #0 // TODO
4983
+ }
4984
+ } else if (false_label != (uint32_t)-1) {
4985
+ | brk #0 // TODO
4986
+ }
4987
+ if (op1_info & MAY_BE_ANY) {
4988
+ if (exit_addr) {
4989
+ if (branch_opcode == ZEND_JMPNZ || branch_opcode == ZEND_JMPNZ_EX) {
4990
+ | brk #0 // TODO
4991
+ }
4992
+ } else if (false_label == (uint32_t)-1) {
4993
+ | brk #0 // TODO
4994
+ }
4995
+ |.code
4996
+ }
4743
4997
}
4744
4998
4745
4999
if (!jmp_done) {
4746
- | brk #0 // TODO
5000
+ if (exit_addr) {
5001
+ | brk #0 // TODO
5002
+ } else if (false_label != (uint32_t)-1) {
5003
+ | brk #0 // TODO
5004
+ } else if (op1_info & MAY_BE_LONG) {
5005
+ | b >9
5006
+ }
4747
5007
}
4748
5008
}
4749
5009
}
4750
5010
4751
5011
if (op1_info & MAY_BE_LONG) {
5012
+ |2:
4752
5013
| brk #0 // TODO
4753
5014
}
4754
5015
0 commit comments