@@ -160,6 +160,14 @@ static bool aarch64_may_encode_addr_offset(int64_t offset, uint32_t type_size)
160
160
|| }
161
161
|.endmacro
162
162
163
+ |.macro ASM_REG_REG_REG_TXT_OP, op, type, dst, src1, src2, txt
164
+ || if (ir_type_size[type] == 8) {
165
+ | op Rx(dst), Rx(src1), Rx(src2), txt
166
+ || } else {
167
+ | op Rw(dst), Rw(src1), Rw(src2), txt
168
+ || }
169
+ |.endmacro
170
+
163
171
|.macro ASM_REG_REG_REG_REG_OP, op, type, dst, src1, src2, src3
164
172
|| if (ir_type_size[type] == 8) {
165
173
| op Rx(dst), Rx(src1), Rx(src2), Rx(src3)
@@ -280,6 +288,7 @@ const char *ir_reg_name(int8_t reg, ir_type type)
280
288
_(DIV_PWR2) \
281
289
_(MOD_PWR2) \
282
290
_(SDIV_PWR2) \
291
+ _(SMOD_PWR2) \
283
292
_(OP_INT) \
284
293
_(OP_FP) \
285
294
_(BINOP_INT) \
@@ -378,10 +387,6 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
378
387
n++;
379
388
}
380
389
break;
381
- case IR_SEXT:
382
- case IR_ZEXT:
383
- flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
384
- IR_FALLTHROUGH;
385
390
case IR_MUL_PWR2:
386
391
case IR_DIV_PWR2:
387
392
case IR_MOD_PWR2:
@@ -432,6 +437,17 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
432
437
}
433
438
}
434
439
break;
440
+ case IR_SMOD_PWR2:
441
+ flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
442
+ insn = &ctx->ir_base[ref];
443
+ n = 0;
444
+ if (IR_IS_CONST_REF(insn->op1)) {
445
+ constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
446
+ n++;
447
+ }
448
+ constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_USE_SUB_REF, IR_SAVE_SUB_REF);
449
+ n++;
450
+ break;
435
451
case IR_CTPOP:
436
452
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG;
437
453
insn = &ctx->ir_base[ref];
@@ -565,6 +581,13 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
565
581
break;
566
582
case IR_COPY_INT:
567
583
case IR_COPY_FP:
584
+ case IR_TRUNC:
585
+ case IR_BITCAST:
586
+ case IR_PROTO:
587
+ flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
588
+ break;
589
+ case IR_ZEXT:
590
+ case IR_SEXT:
568
591
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG;
569
592
break;
570
593
case IR_PARAM:
@@ -582,11 +605,6 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
582
605
case IR_EXITCALL:
583
606
constraints->def_reg = IR_REG_INT_RET1;
584
607
break;
585
- case IR_TRUNC:
586
- case IR_BITCAST:
587
- case IR_PROTO:
588
- flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
589
- break;
590
608
case IR_RSTORE:
591
609
flags = IR_OP3_SHOULD_BE_IN_REG;
592
610
break;
@@ -750,9 +768,12 @@ binop_fp:
750
768
/* pass */
751
769
} else if (IR_IS_CONST_REF(insn->op1)) {
752
770
// const
753
- } else if (IR_IS_TYPE_UNSIGNED(insn->type) && IR_IS_POWER_OF_TWO(op2_insn->val.u64)) {
754
- // TODO: signed division by power of two ???
755
- return IR_MOD_PWR2;
771
+ } else if (IR_IS_POWER_OF_TWO(op2_insn->val.u64)) {
772
+ if (IR_IS_TYPE_UNSIGNED(insn->type)) {
773
+ return IR_MOD_PWR2;
774
+ } else {
775
+ return IR_SMOD_PWR2;
776
+ }
756
777
}
757
778
}
758
779
return IR_BINOP_INT;
@@ -2073,11 +2094,9 @@ static void ir_emit_mul_div_mod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2073
2094
}
2074
2095
} else if (insn->op == IR_DIV) {
2075
2096
uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
2076
- IR_ASSERT(IR_IS_TYPE_UNSIGNED(type));
2077
2097
| ASM_REG_REG_IMM_OP lsr, type, def_reg, op1_reg, shift
2078
2098
} else {
2079
2099
IR_ASSERT(insn->op == IR_MOD);
2080
- IR_ASSERT(IR_IS_TYPE_UNSIGNED(type));
2081
2100
uint64_t mask = ctx->ir_base[insn->op2].val.u64 - 1;
2082
2101
| ASM_REG_REG_IMM_OP and, type, def_reg, op1_reg, mask
2083
2102
}
@@ -2142,6 +2161,50 @@ static void ir_emit_sdiv_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2142
2161
}
2143
2162
}
2144
2163
2164
+ static void ir_emit_smod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2165
+ {
2166
+ ir_backend_data *data = ctx->data;
2167
+ dasm_State **Dst = &data->dasm_state;
2168
+ ir_type type = insn->type;
2169
+ ir_ref op1 = insn->op1;
2170
+ ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
2171
+ ir_reg op1_reg = ctx->regs[def][1];
2172
+ ir_reg tmp_reg = ctx->regs[def][3];
2173
+ // uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
2174
+ uint64_t mask = ctx->ir_base[insn->op2].val.u64 - 1;
2175
+
2176
+ IR_ASSERT(IR_IS_CONST_REF(insn->op2));
2177
+ IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op));
2178
+ IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE && def_reg != tmp_reg);
2179
+
2180
+ if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
2181
+ op1_reg = IR_REG_NUM(op1_reg);
2182
+ ir_emit_load(ctx, type, op1_reg, op1);
2183
+ }
2184
+ if (def_reg != op1_reg) {
2185
+ if (op1_reg != IR_REG_NONE) {
2186
+ ir_emit_mov(ctx, type, def_reg, op1_reg);
2187
+ } else {
2188
+ ir_emit_load(ctx, type, def_reg, op1);
2189
+ }
2190
+ }
2191
+
2192
+ // | ASM_REG_REG_IMM_OP asr, type, tmp_reg, def_reg, (ir_type_size[type]*8-1)
2193
+ // | ASM_REG_REG_IMM_OP lsr, type, tmp_reg, tmp_reg, (ir_type_size[type]*8-shift)
2194
+ // | ASM_REG_REG_REG_OP add, type, def_reg, def_reg, tmp_reg
2195
+ // | ASM_REG_REG_IMM_OP and, type, def_reg, def_reg, mask
2196
+ // | ASM_REG_REG_REG_OP sub, type, def_reg, def_reg, tmp_reg
2197
+
2198
+ | ASM_REG_REG_OP negs, type, tmp_reg, def_reg
2199
+ | ASM_REG_REG_IMM_OP and, type, def_reg, def_reg, mask
2200
+ | ASM_REG_REG_IMM_OP and, type, tmp_reg, tmp_reg, mask
2201
+ | ASM_REG_REG_REG_TXT_OP csneg, type, def_reg, def_reg, tmp_reg, mi
2202
+
2203
+ if (IR_REG_SPILLED(ctx->regs[def][0])) {
2204
+ ir_emit_store(ctx, type, def, def_reg);
2205
+ }
2206
+ }
2207
+
2145
2208
static void ir_emit_shift(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2146
2209
{
2147
2210
ir_backend_data *data = ctx->data;
@@ -5625,6 +5688,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
5625
5688
case IR_SDIV_PWR2:
5626
5689
ir_emit_sdiv_pwr2(ctx, i, insn);
5627
5690
break;
5691
+ case IR_SMOD_PWR2:
5692
+ ir_emit_smod_pwr2(ctx, i, insn);
5693
+ break;
5628
5694
case IR_SHIFT:
5629
5695
ir_emit_shift(ctx, i, insn);
5630
5696
break;
0 commit comments