|
347 | 347 | (rule 0 (lower (has_type (fits_in_32 ty) (umul_overflow x y)))
|
348 | 348 | (let ((tmp_x XReg (zext x))
|
349 | 349 | (tmp_y XReg (zext y))
|
350 |
| - (res XReg (rv_mulhu tmp_x tmp_y)) |
351 |
| - (hi XReg (rv_mul tmp_x tmp_y)) |
352 |
| - (one XReg (imm $I32 1)) |
353 |
| - (of XReg (gen_select_xreg (cmp_eqz res) one (zero_reg)))) |
| 350 | + (res XReg (rv_mul tmp_x tmp_y)) |
| 351 | + (hi XReg (rv_srli res (imm12_const (ty_bits ty)))) |
| 352 | + (one XReg (imm $I8 1)) |
| 353 | + (of XReg (gen_select_xreg (cmp_eqz hi) (zero_reg) one))) |
| 354 | + (output_pair |
| 355 | + (value_reg res) |
| 356 | + (value_reg of)))) |
| 357 | + |
| 358 | +(rule 1 (lower (has_type $I64 (umul_overflow x y))) |
| 359 | + (let ((hi XReg (rv_mulhu x y)) |
| 360 | + (res XReg (rv_mul x y)) |
| 361 | + (one XReg (imm $I8 1)) |
| 362 | + (of XReg (gen_select_xreg (cmp_eqz hi) (zero_reg) one))) |
354 | 363 | (output_pair
|
355 | 364 | (value_reg res)
|
356 | 365 | (value_reg of))))
|
357 | 366 |
|
| 367 | +;; TODO |
| 368 | +(rule 2 (lower (has_type $I128 (umul_overflow x y))) |
| 369 | + (let |
| 370 | + ((x_regs ValueRegs x) |
| 371 | + (x_lo XReg (value_regs_get x_regs 0)) |
| 372 | + (x_hi XReg (value_regs_get x_regs 1)) |
| 373 | + |
| 374 | + ;; Get the high/low registers for `y`. |
| 375 | + (y_regs ValueRegs y) |
| 376 | + (y_lo XReg (value_regs_get y_regs 0)) |
| 377 | + (y_hi XReg (value_regs_get y_regs 1)) |
| 378 | + |
| 379 | + ;; 128bit mul formula: |
| 380 | + ;; dst_lo = x_lo * y_lo |
| 381 | + ;; dst_hi = mulhu(x_lo, y_lo) + (x_lo * y_hi) + (x_hi * y_lo) |
| 382 | + ;; |
| 383 | + ;; We can convert the above formula into the following |
| 384 | + ;; mulhu dst_hi, x_lo, y_lo |
| 385 | + ;; madd dst_hi, x_lo, y_hi, dst_hi |
| 386 | + ;; madd dst_hi, x_hi, y_lo, dst_hi |
| 387 | + ;; madd dst_lo, x_lo, y_lo, zero |
| 388 | + (dst_hi1 XReg (rv_mulhu x_lo y_lo)) |
| 389 | + (one XReg (imm $I32 1)) |
| 390 | + (dst_hi2 ValueRegs (madd_overflow64 x_lo y_hi (value_regs_get dst_hi1 0))) |
| 391 | + (dst_hi ValueRegs (madd_overflow64 x_hi y_lo (value_regs_get dst_hi2 0))) |
| 392 | + (dst_lo XReg (madd x_lo y_lo (zero_reg))) |
| 393 | + |
| 394 | + (of_res1 XReg (rv_or (value_regs_get dst_hi1 1) (value_regs_get dst_hi2 1))) |
| 395 | + (of_res XReg (rv_or of_res1 (value_regs_get dst_hi 1)))) |
| 396 | + (output_pair |
| 397 | + (value_regs dst_lo (value_regs_get dst_hi 0)) |
| 398 | + (value_reg of_res)))) |
| 399 | + |
358 | 400 | ;;;; Rules for `isub` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
359 | 401 | ;; Base case, simply subtracting things in registers.
|
360 | 402 |
|
|
0 commit comments