@@ -251,6 +251,12 @@ inline bool is_valid_immediate(uint64_t val, size_t bits)
251
251
return val < (uint64_t (1 ) << bits);
252
252
}
253
253
254
+ constexpr bool is_valid_immediate_addsub (uint64_t val)
255
+ {
256
+ // 12-bit unsigned immediate value, optionally left-shifted by 12 bits
257
+ return !(val & ~util::make_bitmask<uint64_t >(12 )) || !(val & ~(util::make_bitmask<uint64_t >(12 ) << 12 ));
258
+ }
259
+
254
260
inline constexpr bool is_valid_immediate_signed (int64_t val, size_t bits)
255
261
{
256
262
return util::sext (val, bits) == val;
@@ -752,18 +758,20 @@ a64::Vec drcbe_arm64::be_parameter::select_register(a64::Vec const ®, uint32_
752
758
{
753
759
if (m_type == PTYPE_FLOAT_REGISTER)
754
760
return get_register_float (regsize);
755
- if (regsize == 4 )
761
+ else if (regsize == 4 )
756
762
return reg.s ();
757
- return reg.d ();
763
+ else
764
+ return reg.d ();
758
765
}
759
766
760
767
a64::Gp drcbe_arm64::be_parameter::select_register (a64::Gp const ®, uint32_t regsize) const
761
768
{
762
769
if (m_type == PTYPE_INT_REGISTER)
763
770
return get_register_int (regsize);
764
- if (regsize == 4 )
771
+ else if (regsize == 4 )
765
772
return reg.w ();
766
- return reg.x ();
773
+ else
774
+ return reg.x ();
767
775
}
768
776
769
777
void drcbe_arm64::get_imm_relative (a64::Assembler &a, const a64::Gp ®, const uint64_t val) const
@@ -3234,7 +3242,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_add(a64::Assembler &a, cons
3234
3242
if (Opcode == a64::Inst::kIdAdcs )
3235
3243
load_carry (a);
3236
3244
3237
- if (src1p.is_immediate () && is_valid_immediate (src1p.immediate (), 11 ))
3245
+ if (src1p.is_immediate () && is_valid_immediate_addsub (src1p.immediate ()))
3238
3246
{
3239
3247
const a64::Gp src = src2p.select_register (TEMP_REG2, inst.size ());
3240
3248
@@ -3245,7 +3253,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_add(a64::Assembler &a, cons
3245
3253
a.emit (Opcode, output, src, src1p.immediate ());
3246
3254
mov_param_reg (a, inst.size (), dstp, output);
3247
3255
}
3248
- else if (src2p.is_immediate () && is_valid_immediate (src2p.immediate (), 11 ))
3256
+ else if (src2p.is_immediate () && is_valid_immediate_addsub (src2p.immediate ()))
3249
3257
{
3250
3258
const a64::Gp src = src1p.select_register (TEMP_REG1, inst.size ());
3251
3259
@@ -3285,7 +3293,7 @@ template <a64::Inst::Id Opcode> void drcbe_arm64::op_sub(a64::Assembler &a, cons
3285
3293
3286
3294
const a64::Gp output = dstp.select_register (TEMP_REG3, inst.size ());
3287
3295
3288
- if (src2p.is_immediate () && is_valid_immediate (src2p.immediate (), 11 ))
3296
+ if (src2p.is_immediate () && is_valid_immediate_addsub (src2p.immediate ()))
3289
3297
{
3290
3298
const a64::Gp src = select_register (TEMP_REG1, inst.size ());
3291
3299
@@ -3319,22 +3327,23 @@ void drcbe_arm64::op_cmp(a64::Assembler &a, const uml::instruction &inst)
3319
3327
be_parameter src1p (*this , inst.param (0 ), PTYPE_MRI);
3320
3328
be_parameter src2p (*this , inst.param (1 ), PTYPE_MRI);
3321
3329
3322
- const a64::Gp temp = select_register (TEMP_REG1, inst.size ());
3323
- const a64::Gp temp2 = select_register (TEMP_REG2, inst.size ());
3330
+ const a64::Gp src1 = src1p.select_register (TEMP_REG1, inst.size ());
3324
3331
3325
- mov_reg_param (a, inst.size (), temp , src1p);
3332
+ mov_reg_param (a, inst.size (), src1 , src1p);
3326
3333
3327
- if (src2p.is_immediate () && is_valid_immediate (src2p.immediate (), 11 ))
3334
+ if (src2p.is_immediate () && is_valid_immediate_addsub (src2p.immediate ()))
3328
3335
{
3329
3336
if (src2p.is_immediate_value (0 ))
3330
- a.cmp (temp , select_register (a64::xzr, inst.size ()));
3337
+ a.cmp (src1 , select_register (a64::xzr, inst.size ()));
3331
3338
else
3332
- a.cmp (temp , src2p.immediate ());
3339
+ a.cmp (src1 , src2p.immediate ());
3333
3340
}
3334
3341
else
3335
3342
{
3336
- mov_reg_param (a, inst.size (), temp2, src2p);
3337
- a.cmp (temp, temp2);
3343
+ const a64::Gp src2 = src2p.select_register (TEMP_REG2, inst.size ());
3344
+
3345
+ mov_reg_param (a, inst.size (), src2, src2p);
3346
+ a.cmp (src1, src2);
3338
3347
}
3339
3348
3340
3349
store_carry (a, true );
@@ -3728,17 +3737,35 @@ void drcbe_arm64::op_test(a64::Assembler &a, const uml::instruction &inst)
3728
3737
const a64::Gp src1 = src1p.select_register (TEMP_REG1, inst.size ());
3729
3738
const a64::Gp src2 = src2p.select_register (TEMP_REG2, inst.size ());
3730
3739
3731
- mov_reg_param (a, inst.size (), src1, src1p);
3740
+ if (src1p.is_immediate_value (0 ) || src2p.is_immediate_value (0 ))
3741
+ {
3742
+ const a64::Gp zero = select_register (a64::xzr, inst.size ());
3732
3743
3733
- if (src2p.is_immediate () && is_valid_immediate_mask (src2p.immediate (), inst.size ()))
3744
+ a.tst (zero, zero);
3745
+ }
3746
+ else if (src2p.is_immediate_value (util::make_bitmask<uint64_t >(inst.size () * 8 )))
3734
3747
{
3735
- if (src2p.is_immediate_value (0 ))
3736
- a.tst (src1, select_register (a64::xzr, inst.size ()));
3737
- else
3738
- a.tst (src1, src2p.immediate ());
3748
+ mov_reg_param (a, inst.size (), src1, src1p);
3749
+ a.tst (src1, src1);
3750
+ }
3751
+ else if (src1p.is_immediate_value (util::make_bitmask<uint64_t >(inst.size () * 8 )))
3752
+ {
3753
+ mov_reg_param (a, inst.size (), src2, src2p);
3754
+ a.tst (src2, src2);
3755
+ }
3756
+ else if (src2p.is_immediate () && is_valid_immediate_mask (src2p.immediate (), inst.size ()))
3757
+ {
3758
+ mov_reg_param (a, inst.size (), src1, src1p);
3759
+ a.tst (src1, src2p.immediate ());
3760
+ }
3761
+ else if (src1p.is_immediate () && is_valid_immediate_mask (src1p.immediate (), inst.size ()))
3762
+ {
3763
+ mov_reg_param (a, inst.size (), src2, src2p);
3764
+ a.tst (src2, src1p.immediate ());
3739
3765
}
3740
3766
else
3741
3767
{
3768
+ mov_reg_param (a, inst.size (), src1, src1p);
3742
3769
mov_reg_param (a, inst.size (), src2, src2p);
3743
3770
a.tst (src1, src2);
3744
3771
}
0 commit comments