/*********************************************************************** * 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; });