@@ -122,12 +122,10 @@ typedef struct TLVDescriptor TLVDescriptor;
122122
123123#define IS_SIGNED_32BIT(val) ((((intptr_t)(val)) <= 0x7fffffff) && (((intptr_t)(val)) >= (-2147483647 - 1)))
124124
125- /* Encoding of immediate. TODO: shift mode may be supported in the near future. */
125+ /* Encoding of immediate. */
126126#define MAX_IMM12 0xfff // maximum value for imm12
127127#define MAX_IMM16 0xffff // maximum value for imm16
128- #define CMP_IMM MAX_IMM12 // cmp insn
129128#define MOVZ_IMM MAX_IMM16 // movz insn
130- #define ADD_SUB_IMM MAX_IMM12 // add/sub/adds/subs insn
131129#define LDR_STR_PIMM64 (MAX_IMM12*8) // ldr/str insn for 64-bit register: pimm is imm12 * 8
132130#define LDR_STR_PIMM32 (MAX_IMM12*4) // ldr/str insn for 32-bit register: pimm is imm12 * 4
133131#define LDRB_STRB_PIMM MAX_IMM12 // ldrb/strb insn
@@ -172,6 +170,15 @@ static bool arm64_may_use_adrp(const void *addr)
172170 return 0;
173171}
174172
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+
175182/* Determine whether an immediate value can be encoded as the immediate operand of logical instructions. */
176183static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
177184{
@@ -364,9 +371,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
364371|.macro CMP_32_WITH_CONST, reg, val, tmp_reg
365372|| if (val == 0) {
366373| 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))) {
368375| 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))) {
370377| cmn reg, #-val
371378|| } else {
372379| LOAD_32BIT_VAL tmp_reg, val
@@ -377,9 +384,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
377384|.macro CMP_64_WITH_CONST_32, reg, val, tmp_reg
378385|| if (val == 0) {
379386| 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))) {
381388| 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))) {
383390| cmn reg, #-val
384391|| } else {
385392| LOAD_32BIT_VAL tmp_reg, val
@@ -390,9 +397,9 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
390397|.macro CMP_64_WITH_CONST, reg, val, tmp_reg
391398|| if (val == 0) {
392399| 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))) {
394401| 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))) {
396403| cmn reg, #-val
397404|| } else {
398405| LOAD_64BIT_VAL tmp_reg, val
@@ -406,7 +413,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
406413|.macro ADD_SUB_32_WITH_CONST, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
407414|| if (val == 0) {
408415| 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))) {
410417| add_sub_ins dst_reg, src_reg1, #val
411418|| } else {
412419| LOAD_32BIT_VAL tmp_reg, val
@@ -417,7 +424,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
417424|.macro ADD_SUB_64_WITH_CONST_32, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
418425|| if (val == 0) {
419426| 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))) {
421428| add_sub_ins dst_reg, src_reg1, #val
422429|| } else {
423430| LOAD_32BIT_VAL tmp_reg, val
@@ -428,7 +435,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
428435|.macro ADD_SUB_64_WITH_CONST, add_sub_ins, dst_reg, src_reg1, val, tmp_reg
429436|| if (val == 0) {
430437| 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))) {
432439| add_sub_ins dst_reg, src_reg1, #val
433440|| } else {
434441| LOAD_64BIT_VAL tmp_reg, val
@@ -723,7 +730,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
723730
724731/* Update IP with 32-bit immediate 'val'. */
725732|.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)) );
727734|| if (GCC_GLOBAL_REGS) {
728735| add IP, IP, #val
729736|| } else {
@@ -931,7 +938,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size)
931938 * the computation result is stored back into 'addr'.
932939 * Note: it should be guaranteed that 'val' can be encoded into add/sub instruction. */
933940|.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)) );
935942|| if (Z_MODE(addr) == IS_MEM_ZVAL) {
936943|| if (((uint32_t)(Z_OFFSET(addr))) > LDR_STR_PIMM64) {
937944| 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
82608267 }
82618268
82628269 if (func) {
8263- || if (used_stack <= ADD_SUB_IMM ) {
8270+ || if (arm64_may_encode_imm12((int64_t) used_stack) ) {
82648271 | MEM_UPDATE_ZTS add, ldr, str, #used_stack, executor_globals, vm_stack_top, REG2, TMP1
82658272 || } else {
82668273 | 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
91049111 | LOAD_IP_ADDR (func->op_array.opcodes + num_args)
91059112 } else {
91069113 | 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))) );
91089115 if (GCC_GLOBAL_REGS) {
91099116 | ldr IP, [REG0, #offsetof(zend_op_array, opcodes)]
91109117 if (num_args) {
@@ -9210,7 +9217,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
92109217 | ble >3
92119218 | // zval *var = EX_VAR_NUM(num_args);
92129219 | 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))) );
92149221 | add REG1, REG1, #(ZEND_CALL_FRAME_SLOT * sizeof(zval))
92159222 |2:
92169223 | SET_Z_TYPE_INFO REG1, IS_UNDEF, TMP1w
0 commit comments