1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-02-11 19:05:01 +00:00
Files
pkimpel.retro-b5500/tools/Register.js
2012-12-09 04:18:40 +00:00

191 lines
7.8 KiB
JavaScript

/***********************************************************************
* retro-b5500/emulator Register.js
************************************************************************
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* JavaScript object definition for the generalized Register prototype.
* Maximum register width is 52 bits, since Javascript stores numbers
* internally as 64-bit IEEE 754 floating point numbers. All registers
* implement unsigned arithmetic modulo their bit width.
*
* Constructor spec members:
* width: size of the register in bits.
* value: initial register value (defaults to 0).
************************************************************************
* Modification Log.
* 2012-04-28 P.Kimpel
* Original version, from many frustrating attempts to wrap my head
* around this technique.
***********************************************************************/
define(["exports", "emu/compose"], function(exports, Compose) {
/***********************************************************************
* Register() supports binary registers up to 31 bits in width. Where
* applicable, this constructor is more efficient than LongRegister(),
* since it can use Javascript bitmask operators, which are limited to
* operating on 32-bit SIGNED integers.
***********************************************************************/
var Register = Compose(function(width, value) {
this.width = (width > this.maxBits ? this.maxBits : width);
this.mask = Register.mask2[this.width];
this.modulus = Register.pow2[this.width];
this.bits = (value ? value % this.modulus : 0); // initial register value
},{
maxBits: 31, // maximum register size
isolate: function(start, width) {
var ue = this.width-start; // upper power exponent
var le = ue-width; // lower power exponent
return (le > 0 ? this.bits >>> le : this.bits) & Register.mask2[width];
},
bit: function(bit) {
var e = this.width - bit - 1;
return (e > 0 ? this.bits >>> e : this.bits) & 1;
},
insert: function(start, width, value) {
var ue = this.width-start; // upper power exponent
var le = ue-width; // lower power exponent
this.bits = (this.bits & ((this.mask & ~Register.mask2[ue]) | Register.mask2[le])) |
((value & Register.mask2[width]) << le);
},
bitSet: function(bit) {
this.bits |= Register.pow2[bit];
},
bitReset: function(bit) {
this.bits &= ~Register.pow2[bit];
},
add: function(value) {
var temp = this.bits + value;
this.bits = (temp < 0 ? (this.modulus + temp) : temp) & this.mask;
},
sub: function(value) {
var temp = this.bits - value;
this.bits = (temp < 0 ? (this.modulus + temp) : temp) & this.mask;
},
set: function(value) {
this.bits = (value < 0 ? -value : value) & this.mask;
},
valueOf: function() {
return this.bits;
},
toString: function(radix) {
return this.bits.toString(radix)
}
});
Register.pow2 = [ // powers of 2 from 0 to 52
1, 2, 4, 8,
16, 32, 64, 128,
256, 512, 1024, 2048,
4096, 8192, 16384, 32768,
65536, 131072, 262144, 524288,
1048576, 2097152, 4194304, 8388608,
16777216, 33554432, 67108864, 134217728,
268435456, 536870912, 1073741824, 2147483648,
4294967296, 8589934592, 17179869184, 34359738368,
68719476736, 137438953472, 274877906944, 549755813888,
1099511627776, 2199023255552, 4398046511104, 8796093022208,
17592186044416, 35184372088832, 70368744177664, 140737488355328,
281474976710656, 562949953421312, 1125899906842624, 2251799813685248,
4503599627370496];
Register.mask2 = [ // (2**n)-1 for n from 0 to 52
0, 1, 3, 7,
15, 31, 63, 127,
255, 511, 1023, 2047,
4095, 8191, 16383, 32767,
65535, 131071, 262143, 524287,
1048575, 2097151, 4194303, 8388607,
16777215, 33554431, 67108863, 134217727,
268435455, 536870911, 1073741823, 2147483647,
4294967295, 8589934591, 17179869183, 34359738367,
68719476735, 137438953471, 274877906943, 549755813887,
1099511627775, 2199023255551, 4398046511103, 8796093022207,
17592186044415, 35184372088831, 70368744177663, 140737488355327,
281474976710655, 562949953421311, 1125899906842623, 2251799813685247,
4503599627370495];
/***********************************************************************
* LongRegister() supports binary registers up to 52 bits in width.
* Since Javascript bitmask operators only with up to 32 bits, this
* contructor must use div/mod operations to manipulate the bit fields.
***********************************************************************/
var LongRegister = Compose(Register, {
maxBits: 52, // maximum register size
isolate: function(start, width) {
var ue = this.width-start; // upper power exponent
var le = ue-width; // lower power exponent
return (le > 0 ? Math.floor(this.bits/Register.pow2[le]) : this.bits) % Register.pow2[width];
},
bit: function(bit) {
var e = this.width - bit - 1;
return (e > 0 ? Math.floor(this.bits/Register.pow2[e]) : this.bits) % 2;
},
insert: function(start, width, value) {
var ue = this.width-start; // upper power exponent
var le = ue-width; // lower power exponent
var tpower; // top portion power of 2
var bpower = Register.pow2[le]; // bottom portion power of 2
var top = 0; // unaffected top portion of register
var bottom = 0; // unaffected bottom portion of register
if (start > 0) {
tpower = Register.pow2[ue];
top = Math.floor(this.bits/tpower)*tpower;
}
if (le > 0) {
bottom = this.bits % bpower;
}
this.bits = (value % Register.pow2[width])*bpower + top + bottom;
},
bitSet: function(bit) {
this.insert(bit, 1, 1);
},
bitReset: function(bit) {
this.insert(bit, 1, 0);
},
add: function(value) {
var temp = this.bits + value;
this.bits = (temp < 0 ? (this.modulus + temp) : temp) % this.modulus;
},
sub: function(value) {
var temp = this.bits - value;
this.bits = (temp < 0 ? (this.modulus + temp) : temp) % this.modulus;
},
set: function(value) {
this.bits = (value < 0 ? -value : value) % this.modulus;
}
});
exports.Register = Register;
exports.LongRegister = LongRegister;
});