mirror of
https://github.com/openwrt/video.git
synced 2026-05-31 06:51:54 +08:00
df0b899123
Update WPEWebKit to the 2.52 stable major release branch. Includes a pending patchset to get WASM BBQJIT working on RISCV64, upstream PR https://github.com/WebKit/WebKit/pull/65621 Alltogether this brings acceptable performance (even with LLVMPipe Mesa software renderer) on RISCV64. Link: https://wpewebkit.org/release/wpewebkit-2.52.0.html Link: https://wpewebkit.org/release/wpewebkit-2.52.1.html Link: https://wpewebkit.org/release/wpewebkit-2.52.2.html Link: https://wpewebkit.org/release/wpewebkit-2.52.3.html Signed-off-by: Daniel Golle <daniel@makrotopia.org>
204 lines
9.6 KiB
Diff
204 lines
9.6 KiB
Diff
--- a/Source/JavaScriptCore/offlineasm/riscv64.rb
|
|
+++ b/Source/JavaScriptCore/offlineasm/riscv64.rb
|
|
@@ -122,6 +122,12 @@ def riscv64OperandTypes(operands)
|
|
else
|
|
raise "Invalid Tmp operand #{op.kind}"
|
|
end
|
|
+ elsif op.is_a? VecRegisterID
|
|
+ # Vector registers are aliased to single FPRs on RISC-V (no V
|
|
+ # extension); treat them as FPRegisterID for validation so the
|
|
+ # existing [Address, FPRegisterID] / [FPRegisterID, Address]
|
|
+ # patterns match loadv/storev/pushv/popv operands.
|
|
+ FPRegisterID
|
|
else
|
|
op.class
|
|
end
|
|
@@ -273,6 +279,40 @@ class FPRegisterID
|
|
end
|
|
end
|
|
|
|
+class VecRegisterID
|
|
+ # Pseudo-vector registers v0..v7 (and lane variants) for the IPInt
|
|
+ # interpreter, which stores every wasm operand-stack value in a
|
|
+ # 16-byte slot regardless of type. RISC-V baseline rv64gc has no V
|
|
+ # extension and no 128-bit register, so each v-reg is aliased to a
|
|
+ # single 64-bit FPR (the low half of the slot); pushv/popv/loadv/
|
|
+ # storev below operate on 16-byte slots but only move 8 bytes of
|
|
+ # payload. Safe because wasm SIMD is gated off at runtime
|
|
+ # (Options::useWasmSIMD = false on RISCV64) so the upper 8 bytes
|
|
+ # are pure padding.
|
|
+ def riscv64Operand
|
|
+ case @name
|
|
+ when 'v0', 'v0_b', 'v0_h', 'v0_i', 'v0_q'
|
|
+ 'f0'
|
|
+ when 'v1', 'v1_b', 'v1_h', 'v1_i', 'v1_q'
|
|
+ 'f1'
|
|
+ when 'v2', 'v2_b', 'v2_h', 'v2_i', 'v2_q'
|
|
+ 'f2'
|
|
+ when 'v3', 'v3_b', 'v3_h', 'v3_i', 'v3_q'
|
|
+ 'f3'
|
|
+ when 'v4', 'v4_b', 'v4_h', 'v4_i', 'v4_q'
|
|
+ 'f4'
|
|
+ when 'v5', 'v5_b', 'v5_h', 'v5_i', 'v5_q'
|
|
+ 'f5'
|
|
+ when 'v6', 'v6_b', 'v6_h', 'v6_i', 'v6_q'
|
|
+ 'f6'
|
|
+ when 'v7', 'v7_b', 'v7_h', 'v7_i', 'v7_q'
|
|
+ 'f7'
|
|
+ else
|
|
+ raise "Bad vector register name #{@name} at #{codeOriginString}"
|
|
+ end
|
|
+ end
|
|
+end
|
|
+
|
|
class SpecialRegister
|
|
def riscv64Operand
|
|
@name
|
|
@@ -651,6 +691,43 @@ def riscv64LowerOperation(list)
|
|
newList << Instruction.new(node.codeOrigin, "rv_addi", [sp, Immediate.new(node.codeOrigin, size), sp])
|
|
end
|
|
|
|
+ # pushv / popv reserve 16 bytes per operand because the IPInt wasm
|
|
+ # operand stack uses 16-byte slots uniformly. RISC-V baseline rv64gc
|
|
+ # has no V extension, so each v-reg is aliased to a single 64-bit FPR;
|
|
+ # only the low 8 bytes are written/read, the upper 8 bytes are pure
|
|
+ # padding (wasm SIMD is disabled at runtime on this arch).
|
|
+ def emitPushv(newList, node)
|
|
+ sp = RegisterID.forName(node.codeOrigin, 'sp')
|
|
+ size = 16 * node.operands.size
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_addi", [sp, Immediate.new(node.codeOrigin, -size), sp])
|
|
+ node.operands.reverse.each_with_index {
|
|
+ | op, index |
|
|
+ offset = size - 16 * (index + 1)
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_fsd", [op, Address.new(node.codeOrigin, sp, Immediate.new(node.codeOrigin, offset))])
|
|
+ }
|
|
+ end
|
|
+
|
|
+ def emitPopv(newList, node)
|
|
+ sp = RegisterID.forName(node.codeOrigin, 'sp')
|
|
+ size = 16 * node.operands.size
|
|
+ node.operands.each_with_index {
|
|
+ | op, index |
|
|
+ offset = size - 16 * (index + 1)
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_fld", [Address.new(node.codeOrigin, sp, Immediate.new(node.codeOrigin, offset)), op])
|
|
+ }
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_addi", [sp, Immediate.new(node.codeOrigin, size), sp])
|
|
+ end
|
|
+
|
|
+ def emitLoadv(newList, node)
|
|
+ riscv64ValidateOperands(node.operands, [Address, FPRegisterID])
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_fld", node.operands)
|
|
+ end
|
|
+
|
|
+ def emitStorev(newList, node)
|
|
+ riscv64ValidateOperands(node.operands, [FPRegisterID, Address])
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_fsd", node.operands)
|
|
+ end
|
|
+
|
|
def emitAdditionOperation(newList, node, operation, size)
|
|
operands = node.operands
|
|
if operands.size == 2
|
|
@@ -790,38 +867,56 @@ def riscv64LowerOperation(list)
|
|
def emitBitExtensionOperation(newList, node, extension, fromSize, toSize)
|
|
raise "Invalid operand types" unless riscv64OperandTypes(node.operands) == [RegisterID, RegisterID]
|
|
|
|
- if [[:s, :i, :p], [:s, :i, :q]].include? [extension, fromSize, toSize]
|
|
- newList << Instruction.new(node.codeOrigin, "rv_sext.w", node.operands)
|
|
- return
|
|
- end
|
|
-
|
|
source = node.operands[0]
|
|
dest = node.operands[1]
|
|
|
|
- if [[:z, :i, :p], [:z, :i, :q]].include? [extension, fromSize, toSize]
|
|
+ # On RISC-V :p (pointer) is the same width as :q (64-bit).
|
|
+ targetSize = (toSize == :p) ? :q : toSize
|
|
+
|
|
+ case [extension, fromSize, targetSize]
|
|
+ when [:s, :i, :q]
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_sext.w", [source, dest])
|
|
+ return
|
|
+ when [:s, :i, :i]
|
|
+ # Already an i32 in canonical RISC-V form (low 32 bits = value,
|
|
+ # upper 32 bits = sign-extension of bit 31). sext.w re-normalises
|
|
+ # in case the source was produced by a non-canonical sequence.
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_sext.w", [source, dest])
|
|
+ return
|
|
+ when [:z, :i, :q]
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 32), dest])
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_srli", [dest, Immediate.new(node.codeOrigin, 32), dest])
|
|
+ return
|
|
+ when [:z, :i, :i]
|
|
+ # Lower 32 bits of source already hold the value; clearing the
|
|
+ # upper 32 bits gives the :i canonical representation.
|
|
newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 32), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srli", [dest, Immediate.new(node.codeOrigin, 32), dest])
|
|
return
|
|
end
|
|
|
|
- raise "Invalid zero extension" unless extension == :s
|
|
- case [fromSize, toSize]
|
|
- when [:b, :i]
|
|
+ case [extension, fromSize, targetSize]
|
|
+ when [:s, :b, :i]
|
|
newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 56), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srai", [dest, Immediate.new(node.codeOrigin, 24), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srli", [dest, Immediate.new(node.codeOrigin, 32), dest])
|
|
- when [:b, :q]
|
|
+ when [:s, :b, :q]
|
|
newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 56), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srai", [dest, Immediate.new(node.codeOrigin, 56), dest])
|
|
- when [:h, :i]
|
|
+ when [:s, :h, :i]
|
|
newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 48), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srai", [dest, Immediate.new(node.codeOrigin, 16), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srli", [dest, Immediate.new(node.codeOrigin, 32), dest])
|
|
- when [:h, :q]
|
|
+ when [:s, :h, :q]
|
|
newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 48), dest])
|
|
newList << Instruction.new(node.codeOrigin, "rv_srai", [dest, Immediate.new(node.codeOrigin, 48), dest])
|
|
+ when [:z, :b, :i], [:z, :b, :q]
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_andi", [source, Immediate.new(node.codeOrigin, 0xff), dest])
|
|
+ when [:z, :h, :i], [:z, :h, :q]
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_slli", [source, Immediate.new(node.codeOrigin, 48), dest])
|
|
+ newList << Instruction.new(node.codeOrigin, "rv_srli", [dest, Immediate.new(node.codeOrigin, 48), dest])
|
|
else
|
|
- raise "Invalid bit-extension combination"
|
|
+ raise "Invalid bit-extension combination #{[extension, fromSize, toSize]}"
|
|
end
|
|
end
|
|
|
|
@@ -882,6 +977,14 @@ def riscv64LowerOperation(list)
|
|
emitPush(newList, node)
|
|
when "pop"
|
|
emitPop(newList, node)
|
|
+ when "pushv"
|
|
+ emitPushv(newList, node)
|
|
+ when "popv"
|
|
+ emitPopv(newList, node)
|
|
+ when "loadv"
|
|
+ emitLoadv(newList, node)
|
|
+ when "storev"
|
|
+ emitStorev(newList, node)
|
|
when /^(add|sub)(i|p|q)$/
|
|
emitAdditionOperation(newList, node, $1.to_sym, $2.to_sym)
|
|
when /^(mul|div|rem)(i|p|q)(s?)$/
|
|
@@ -1543,8 +1646,7 @@ def riscv64GenerateWASMPlaceholders(list
|
|
if node.is_a? Instruction
|
|
case node.opcode
|
|
when "loadlinkacqb", "loadlinkacqh", "loadlinkacqi", "loadlinkacqq",
|
|
- "storecondrelb", "storecondrelh", "storecondreli", "storecondrelq",
|
|
- "loadv", "storev"
|
|
+ "storecondrelb", "storecondrelh", "storecondreli", "storecondrelq"
|
|
newList << Instruction.new(node.codeOrigin, "rv_ebreak", [], "WebAssembly placeholder for opcode #{node.opcode}")
|
|
else
|
|
newList << node
|
|
@@ -1570,6 +1672,7 @@ class Sequence
|
|
false
|
|
end
|
|
}
|
|
+ result = riscLowerMalformedAddressesDouble(result)
|
|
result = riscv64LowerMisplacedAddresses(result)
|
|
result = riscLowerMisplacedAddresses(result)
|
|
result = riscv64LowerAddressLoads(result)
|