@@ -122,12 +122,10 @@ typedef struct TLVDescriptor TLVDescriptor;
122
122
123
123
#define IS_SIGNED_32BIT(val) ((((intptr_t)(val)) <= 0x7fffffff) && (((intptr_t)(val)) >= (-2147483647 - 1)))
124
124
125
- /* Encoding of immediate. TODO: shift mode may be supported in the near future. */
125
+ /* Encoding of immediate. */
126
126
#define MAX_IMM12 0xfff // maximum value for imm12
127
127
#define MAX_IMM16 0xffff // maximum value for imm16
128
- #define CMP_IMM MAX_IMM12 // cmp insn
129
128
#define MOVZ_IMM MAX_IMM16 // movz insn
130
- #define ADD_SUB_IMM MAX_IMM12 // add/sub/adds/subs insn
131
129
#define LDR_STR_PIMM64 (MAX_IMM12*8) // ldr/str insn for 64-bit register: pimm is imm12 * 8
132
130
#define LDR_STR_PIMM32 (MAX_IMM12*4) // ldr/str insn for 32-bit register: pimm is imm12 * 4
133
131
#define LDRB_STRB_PIMM MAX_IMM12 // ldrb/strb insn
@@ -172,6 +170,15 @@ static bool arm64_may_use_adrp(const void *addr)
172
170
return 0;
173
171
}
174
172
173
+ /* Determine whether "val" falls into two allowed ranges:
174
+ * Range 1: [0, 0xfff]
175
+ * Range 2: LSL #12 to Range 1
176
+ * Used to guard the immediate encoding for add/adds/sub/subs/cmp/cmn instructions. */
177
+ static bool arm64_may_encode_imm12(const int64_t val)
178
+ {
179
+ return (val >= 0 && (val <= MAX_IMM12 || !(val & 0xffffffffff000fff)));
180
+ }
181
+
175
182
/* Determine whether an immediate value can be encoded as the immediate operand of logical instructions. */
176
183
static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
177
184
{
@@ -364,9 +371,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
364
371
|.macro CMP_32_WITH_CONST, reg, val, tmp_reg
365
372
|| if (val == 0) {
366
373
| cmp reg, wzr
367
- || } else if (((int32_t )(val)) > 0 && ((int32_t)(val)) <= CMP_IMM ) {
374
+ || } else if (arm64_may_encode_imm12((int64_t )(val))) {
368
375
| cmp reg, #val
369
- || } else if (((int32_t)( val)) < 0 && ((int32_t)(val)) >= -CMP_IMM ) {
376
+ || } else if (arm64_may_encode_imm12((int64_t)(- val))) {
370
377
| cmn reg, #-val
371
378
|| } else {
372
379
| LOAD_32BIT_VAL tmp_reg, val
@@ -377,9 +384,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
377
384
|.macro CMP_64_WITH_CONST_32, reg, val, tmp_reg
378
385
|| if (val == 0) {
379
386
| cmp reg, xzr
380
- || } else if (((int32_t )(val)) > 0 && ((int32_t)(val)) <= CMP_IMM ) {
387
+ || } else if (arm64_may_encode_imm12((int64_t )(val))) {
381
388
| cmp reg, #val
382
- || } else if (((int32_t)( val)) < 0 && ((int32_t)(val)) >= -CMP_IMM ) {
389
+ || } else if (arm64_may_encode_imm12((int64_t)(- val))) {
383
390
| cmn reg, #-val
384
391
|| } else {
385
392
| LOAD_32BIT_VAL tmp_reg, val
@@ -390,9 +397,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
390
397
|.macro CMP_64_WITH_CONST, reg, val, tmp_reg
391
398
|| if (val == 0) {
392
399
| cmp reg, xzr
393
- || } else if (((int64_t)(val)) > 0 && ((int64_t)(val)) <= CMP_IMM ) {
400
+ || } else if (arm64_may_encode_imm12 ((int64_t)(val))) {
394
401
| cmp reg, #val
395
- || } else if (((int64_t)(val)) < 0 && ((int64_t)(val)) >= -CMP_IMM ) {
402
+ || } else if (arm64_may_encode_imm12 ((int64_t)(- val))) {
396
403
| cmn reg, #-val
397
404
|| } else {
398
405
| LOAD_64BIT_VAL tmp_reg, val
@@ -406,7 +413,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
406
413
|.macro ADD_SUB_32_WITH_CONST, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
407
414
|| if (val == 0) {
408
415
| add_sub_ins dst_reg, src_reg1, wzr
409
- || } else if (((int32_t )(val)) > 0 && ((int32_t)(val)) <= ADD_SUB_IMM ) {
416
+ || } else if (arm64_may_encode_imm12((int64_t )(val))) {
410
417
| add_sub_ins dst_reg, src_reg1, #val
411
418
|| } else {
412
419
| LOAD_32BIT_VAL tmp_reg, val
@@ -417,7 +424,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
417
424
|.macro ADD_SUB_64_WITH_CONST_32, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
418
425
|| if (val == 0) {
419
426
| add_sub_ins dst_reg, src_reg1, xzr
420
- || } else if (((int32_t )(val)) > 0 && ((int32_t)(val)) <= ADD_SUB_IMM ) {
427
+ || } else if (arm64_may_encode_imm12((int64_t )(val))) {
421
428
| add_sub_ins dst_reg, src_reg1, #val
422
429
|| } else {
423
430
| LOAD_32BIT_VAL tmp_reg, val
@@ -428,7 +435,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
428
435
|.macro ADD_SUB_64_WITH_CONST, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
429
436
|| if (val == 0) {
430
437
| add_sub_ins dst_reg, src_reg1, xzr
431
- || } else if (((int64_t)(val)) > 0 && ((int64_t)(val)) <= ADD_SUB_IMM ) {
438
+ || } else if (arm64_may_encode_imm12 ((int64_t)(val))) {
432
439
| add_sub_ins dst_reg, src_reg1, #val
433
440
|| } else {
434
441
| LOAD_64BIT_VAL tmp_reg, val
@@ -723,7 +730,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
723
730
724
731
/* Update IP with 32-bit immediate 'val'. */
725
732
|.macro ADD_IP_WITH_CONST, val, tmp_reg
726
- || ZEND_ASSERT(val >= 0 && val <= ADD_SUB_IMM );
733
+ || ZEND_ASSERT(arm64_may_encode_imm12((int64_t)( val)) );
727
734
|| if (GCC_GLOBAL_REGS) {
728
735
| add IP, IP, #val
729
736
|| } else {
@@ -931,7 +938,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
931
938
* the computation result is stored back into 'addr'.
932
939
* Note: it should be guaranteed that 'val' can be encoded into add/sub instruction. */
933
940
|.macro LONG_ADD_SUB_WITH_IMM, add_sub_ins, addr, val, tmp_reg1, tmp_reg2
934
- || ZEND_ASSERT(val >= 0 && val <= ADD_SUB_IMM );
941
+ || ZEND_ASSERT(arm64_may_encode_imm12((int64_t)( val)) );
935
942
|| if (Z_MODE(addr) == IS_MEM_ZVAL) {
936
943
|| if (((uint32_t)(Z_OFFSET(addr))) > LDR_STR_PIMM64) {
937
944
| LOAD_32BIT_VAL tmp_reg2, Z_OFFSET(addr)
@@ -8260,7 +8267,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
8260
8267
}
8261
8268
8262
8269
if (func) {
8263
- || if (used_stack <= ADD_SUB_IMM ) {
8270
+ || if (arm64_may_encode_imm12((int64_t) used_stack) ) {
8264
8271
| MEM_UPDATE_ZTS add, ldr, str, #used_stack, executor_globals, vm_stack_top, REG2, TMP1
8265
8272
|| } else {
8266
8273
| LOAD_32BIT_VAL TMP1w, used_stack
@@ -9104,7 +9111,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
9104
9111
| LOAD_IP_ADDR (func->op_array.opcodes + num_args)
9105
9112
} else {
9106
9113
| ldr REG0, EX->func
9107
- || ZEND_ASSERT(( num_args * sizeof(zend_op)) <= ADD_SUB_IMM );
9114
+ || ZEND_ASSERT(arm64_may_encode_imm12((int64_t)( num_args * sizeof(zend_op))) );
9108
9115
if (GCC_GLOBAL_REGS) {
9109
9116
| ldr IP, [REG0, #offsetof(zend_op_array, opcodes)]
9110
9117
if (num_args) {
@@ -9210,7 +9217,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
9210
9217
| ble >3
9211
9218
| // zval *var = EX_VAR_NUM(num_args);
9212
9219
| add REG1, FP, REG1, lsl #4
9213
- || ZEND_ASSERT(ZEND_CALL_FRAME_SLOT * sizeof(zval) <= ADD_SUB_IMM );
9220
+ || ZEND_ASSERT(arm64_may_encode_imm12((int64_t)( ZEND_CALL_FRAME_SLOT * sizeof(zval))) );
9214
9221
| add REG1, REG1, #(ZEND_CALL_FRAME_SLOT * sizeof(zval))
9215
9222
|2:
9216
9223
| SET_Z_TYPE_INFO REG1, IS_UNDEF, TMP1w
0 commit comments