- 加法(c = a + b) - 减法(c = a - b) - 除法(c = a / b) - 乘法(c = a * b) - 取模(c = a%b) - 最小值(c = min(a,b)) - 最大值(c = max(a,b)) - 比较(c =(a < b),c =(a == b),c =(a <= b),等等。) - 跳转(goto,for,et.c.)
我要支持的位运算是:
- 或(c = a | b) - 与(c = a&b) - 异或(c = a ^ b) - 左移(c = a << b) - 右移(c = a >> b)(所有整数都是有符号的,因此这是个问题) - 带符号移位(c = a >>> b) - 取反(a = ~b)(已经找到解决方案,请参见下文)
通常问题是如何使用位操作来实现算术优化。 但在这种情况下不是这样。
在这种体系结构上,可写内存非常稀缺,因此需要进行位运算。位运算本身不应使用大量临时变量。 但是,常量只读数据和指令内存非常充足。 这里还有一个副注,跳转和分支不昂贵,并且所有数据都可以缓存。 跳转的成本是算术(包括加载/存储)指令的一半。 换句话说,以上所有受支持的函数的成本是单个跳转的两倍。
一些可能有用的思考:
我发现您可以使用以下代码完成取反(否定位):
// Bitwise one's complement
b = ~a;
// Arithmetic one's complement
b = -1 - a;
我还记得以前的一种通过除以2的幂次来实现位移操作的方法,具体为:
// Bitwise left shift
b = a << 4;
// Arithmetic left shift
b = a * 16; // 2^4 = 16
// Signed right shift
b = a >>> 4;
// Arithmetic right shift
b = a / 16;
对于其他位运算,我有点不太了解。我希望这个架构的设计者能提供位运算。
我还想知道是否有一种快速/简单的方法来计算2的幂次方(用于移位操作),而不使用内存数据表。一个朴素的解决方案是跳入乘法领域:
b = 1;
switch (a)
{
case 15: b = b * 2;
case 14: b = b * 2;
// ... exploting fallthrough (instruction memory is magnitudes larger)
case 2: b = b * 2;
case 1: b = b * 2;
}
或者采用"设置和跳转"的方法:
switch (a)
{
case 15: b = 32768; break;
case 14: b = 16384; break;
// ... exploiting the fact that a jump is faster than one additional mul
// at the cost of doubling the instruction memory footprint.
case 2: b = 4; break;
case 1: b = 2; break;
}