Floating Numeric Instructions
撰写时间:2025-01-23
修订时间:2025-01-24
与浮点数有关的指令
nn, mm ::= 32 | 64
sx ::= u | s
instr ::= fnn.const fnn
| fnn.funop
| fnn.fbinop
| fnn.frelop
| f32.demote_f64 | f64.promote_f32 | fnn.convert_imm_sx
| fnn.reinterpret_inn
| ...
funop ::= abs | neg | sqrt | ceil | floor | trunc | nearest
fbinop ::= add | sub | mul | div | min | max | copysign
frelop ::= eq | ne | lt | gt | le | ge
设置常数
fnn.const fnn将一个浮点数常数压进Result Stack中。
let watSrc = `
(module
(func (export "sum") (result f32)
f32.const 0.3
f32.const 0.5
f32.add
)
)
`;
const { sum } = await WabtUtils.RunWat(watSrc);
pc.log(sum());
i64也同样适用于const指令。
let watSrc = `
(module
(func (export "sub") (result f64)
f64.const 0.7
f64.const 0.25
f64.sub
)
)
`;
const { sub } = await WabtUtils.RunWat(watSrc);
let result = sub();
pc.log(result);
pc.log(typeof result);
一元操作指令
一元操作指令是指只有1个操作数的指令,在语法表中使用funop (floating unary operations) 来标识。
abs
abs指令,absolute
的缩写,返回操作数的绝对值。
let watSrc = `
(module
(func (export "abs") (param f32) (result f32)
local.get 0
f32.abs
)
)
`;
const { abs } = await WabtUtils.RunWat(watSrc);
let num = -2.3;
pc.log(abs(num));
neg
neg指令,negate
的缩写,反转操作数的正负符号。
let watSrc = `
(module
(func (export "neg") (param f32) (result f32)
local.get 0
f32.neg
)
)
`;
const { neg } = await WabtUtils.RunWat(watSrc);
let num = -2.3;
pc.log(neg(num));
sqrt
sqrt指令,square root
的缩写,返回操作数的平方根。
let watSrc = `
(module
(func (export "sqrt") (param f32) (result f32)
local.get 0
f32.sqrt
)
)
`;
const { sqrt } = await WabtUtils.RunWat(watSrc);
let num = 81;
pc.log(sqrt(num));
ceil
ceil指令,返回操作数在笛卡尔坐标系Y轴中向上取整的整数。
let watSrc = `
(module
(func (export "ceil") (param f32) (result f32)
local.get 0
f32.ceil
)
)
`;
const { ceil } = await WabtUtils.RunWat(watSrc);
pc.log(ceil(3.51));
pc.log(ceil(-3.51));
floor
floor指令,返回操作数在笛卡尔坐标系Y轴中向下取整的整数。
let watSrc = `
(module
(func (export "floor") (param f32) (result f32)
local.get 0
f32.floor
)
)
`;
const { floor } = await WabtUtils.RunWat(watSrc);
pc.log(floor(3.51));
pc.log(floor(-3.51));
trunc
trunc指令,舍弃操作数的小数部分,只保留整数。
let watSrc = `
(module
(func (export "trunc") (param f32) (result f32)
local.get 0
f32.trunc
)
)
`;
const { trunc } = await WabtUtils.RunWat(watSrc);
pc.log(trunc(3.51));
pc.log(trunc(-3.51));
nearest
nearest指令,四舍五入。
let watSrc = `
(module
(func (export "nearest") (param f32) (result f32)
local.get 0
f32.nearest
)
)
`;
const { nearest } = await WabtUtils.RunWat(watSrc);
pc.log(nearest(3.51));
pc.log(nearest(-3.21));
二元操作指令
二元操作指令是指有2个操作数的指令,在语法表中使用fbinop (floating binnary operations) 来标识。
add
add指令,将两个操作数相加。
let watSrc = `
(module
(func (export "add") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.add
)
)
`;
const { add } = await WabtUtils.RunWat(watSrc);
pc.log(add(1.2, 3.4));
sub
sub指令,从第一个操作数减去第二个操作数。
let watSrc = `
(module
(func (export "sub") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.sub
)
)
`;
const { sub } = await WabtUtils.RunWat(watSrc);
pc.log(sub(1.2, 3.4));
mul
mul指令,将两个操作数相乘。
let watSrc = `
(module
(func (export "mul") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.mul
)
)
`;
const { mul } = await WabtUtils.RunWat(watSrc);
pc.log(mul(1.5, 3.0));
div
div指令,从第一个操作数除以第二个操作数。
let watSrc = `
(module
(func (export "div") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.div
)
)
`;
const { div } = await WabtUtils.RunWat(watSrc);
pc.log(div(4.5, 3.0));
min
min指令,从两个操作数中取最小值。
let watSrc = `
(module
(func (export "min") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.min
)
)
`;
const { min } = await WabtUtils.RunWat(watSrc);
pc.log(min(4.5, 3.2));
max
max指令,从两个操作数中取最小值。
let watSrc = `
(module
(func (export "max") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.max
)
)
`;
const { max } = await WabtUtils.RunWat(watSrc);
pc.log(max(4.5, 3.2));
copysign
copysign指令,产生一个新数,其数值取自第一个操作数,而符号位取自第二个操作数。
let watSrc = `
(module
(func (export "copysign") (param f32 f32) (result f32)
local.get 0
local.get 1
f32.copysign
)
)
`;
const { copysign } = await WabtUtils.RunWat(watSrc);
let num1 = 4.5;
let num2 = -3.2;
let result = copysign(num1, num2);
pc.log(result, num1, num2);
比较指令
比较指令消耗2个操作数,返回一个表示真假的数值,1为true,0为false,在语法表中使用frelop (floating relation operations) 来标识。
eq
eq指令,equal
的缩写,用于测试2个操作数的数值是否相等。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "eq") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.eq
)
)
`;
const { eq } = await WabtUtils.RunWat(watSrc);
pc.log(eq(3.5, 3.52));
ne
ne指令,not equal
的缩写,用于测试2个操作数的数值是否不等。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "ne") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.ne
)
)
`;
const { ne } = await WabtUtils.RunWat(watSrc);
pc.log(ne(3.5, 3.52));
lt
lt指令,less than
的缩写,用于测试第1个操作数是否小于第2个操作数。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "lt") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.lt
)
)
`;
const { lt } = await WabtUtils.RunWat(watSrc);
pc.log(lt(1.3, 5.7));
gt
gt指令,greater than
的缩写,用于测试第1个操作数是否大于第2个操作数。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "gt") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.gt
)
)
`;
const { gt } = await WabtUtils.RunWat(watSrc);
pc.log(gt(1.3, 5.7));
le
le指令,less or equal
的缩写,用于测试第1个操作数是否小于等于第2个操作数。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "le") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.le
)
)
`;
const { le } = await WabtUtils.RunWat(watSrc);
pc.log(le(1.3, 5.7));
ge
ge指令,greater or equal
的缩写,用于测试第1个操作数是否大于等于第2个操作数。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "ge") (param f32 f32) (result i32)
local.get 0
local.get 1
f32.ge
)
)
`;
const { ge } = await WabtUtils.RunWat(watSrc);
pc.log(ge(1.3, 5.7));
转换指令
f32.demote_f64
f32.demote_f64指令,将一个f64转换为一个f32。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "demote") (param f64) (result f32)
local.get 0
f32.demote_f64
)
)
`;
const { demote } = await WabtUtils.RunWat(watSrc);
let num = 25.32;
pc.log(num);
pc.log(typeof num);
pc.log("%s", getBinStr(num, 8));
let result = demote(num);
pc.log(result);
pc.log(typeof result);
pc.log("%s", getBinStr(result, 8));
JavaScript的Number类型的数据,均为IEEE 754-2019 ( IEEE Standard for Floating-Point Arithmetic) 标准下的64位双精度数值,因此JavaScript的Number实参可直接传递给Wasm的f64形参。
f64.promote_f32
f64.promote_f32指令,将一个f32转换为一个f64。
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "promote") (param f32) (result f64)
local.get 0
f64.promote_f32
)
)
`;
const { promote } = await WabtUtils.RunWat(watSrc);
let num = 25.32;
pc.log(num);
pc.log(typeof num);
pc.log("%s", getBinStr(num, 8));
let result = promote(num);
pc.log(result);
pc.log(typeof result);
pc.log("%s", getBinStr(result, 8));
convert系列指令
convert系列指令,将一个整数转换为浮点数。需指定是否有符号。
| 指令名称 | 符号标记 | 含义 |
| f32.convert_i32_s | signed | 将i32转换为一个有符号的f32 |
| f32.convert_i32_u | unsigned | 将i32转换为一个无符号的f32 |
| f32.convert_i64_s | signed | 将i64转换为一个有符号的f32 |
| f32.convert_i64_u | unsigned | 将i64转换为一个无符号的f32 |
| f64.convert_i32_s | signed | 将i32转换为一个有符号的f64 |
| f64.convert_i32_u | unsigned | 将i32转换为一个无符号的f64 |
| f64.convert_i64_s | signed | 将i64转换为一个有符号的f64 |
| f64.convert_i64_u | unsigned | 将i64转换为一个无符号的f64 |
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "f32_convert_i32_s") (param i32) (result f32)
local.get 0
f32.convert_i32_s
)
)
`;
const { f32_convert_i32_s } = await WabtUtils.RunWat(watSrc);
let num = -5;
pc.log(f32_convert_i32_s(num));
reinterpret系列指令
reinterpret系列指令,根据一个整数的二进制,重新解释为一个位域相等的浮点数。
| 指令名称 | 含义 |
| f32.reinterpret_i32 | 将i32解释为f32 |
| f64.reinterpret_i64 | 将i64解释为f64 |
const { getBinStr } = await import('/js/esm/BinUtils.js');
let watSrc = `
(module
(func (export "reinterpret") (param i32) (result f32)
local.get 0
f32.reinterpret_i32
)
)
`;
const { reinterpret } = await WabtUtils.RunWat(watSrc);
let num = 5;
pc.log(num);
pc.log("%s", getBinStr(num, 8));
let result = reinterpret(num);
pc.log(result);
pc.log("%s", getBinStr(result, 8));