1964js/coffee/helpers.coffee
2018-06-20 14:37:14 -04:00

685 lines
20 KiB
CoffeeScript

###1964js - JavaScript/HTML5 port of 1964 - N64 emulator
Copyright (C) 2012 Joel Middendorf
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.###
#///////////////
#Operand helpers
#///////////////
#jslint bitwise: true, devel: true, todo: true
#global consts
#global goog, BigInt, bigint_mul, bigint_div, bigint_mod
C1964jsHelpers = (core, isLittleEndian) ->
"use strict"
this.core = core
@isLittleEndian = isLittleEndian
@isBigEndian = (isLittleEndian is false)
@fs = (i) ->
i >> 11 & 0x1f
@ft = (i) ->
i >> 16 & 0x1f
@FS32ArrayView = (i) ->
(i >> 11 & 0x1f) ^ @isBigEndian
@FS32HIArrayView = (i) ->
(i >> 11 & 0x1f) ^ @isLittleEndian
@FT32ArrayView = (i) ->
(i >> 16 & 0x1f) ^ @isBigEndian
@FT32HIArrayView = (i) ->
(i >> 16 & 0x1f) ^ @isLittleEndian
@FD32ArrayView = (i) ->
(i >> 6 & 0x1F) ^ @isBigEndian
@FD32HIArrayView = (i) ->
(i >> 6 & 0x1f) ^ @isLittleEndian
@FS64ArrayView = (i) ->
(i >> 11 & 0x1f) >> 1
@FT64ArrayView = (i) ->
(i >> 16 & 0x1f) >> 1
@FD64ArrayView = (i) ->
(i >> 6 & 0x1F) >> 1
@rd = (i) ->
i >> 11 & 0x1f
@rs = (i) ->
i >> 21 & 0x1f
@RS = (i) ->
reg = (i >> 21 & 0x1f)
return "~-1" if reg is 0
"r[" + reg + "]"
@RSH = (i) ->
reg = (i >> 21 & 0x1f)
return "~-1" if reg is 0
"h[" + reg + "]"
@uRS = (i) ->
reg = (i >> 21 & 0x1f)
return "~-1" if reg is 0
"(r[" + reg + "]>>>0)"
@uRSH = (i) ->
reg = (i >> 21 & 0x1f)
return "~-1" if reg is 0
"(h[" + reg + "]>>>0)"
@tRS = (i) ->
reg = (i >> 21 & 0x1f)
return "r[34]" if reg is 0
"r[" + reg + "]"
@tRSH = (i) ->
reg = (i >> 21 & 0x1f)
return "h[34]" if reg is 0
"h[" + reg + "]"
@tRD = (i) ->
reg = (i >> 11 & 0x1f)
return "r[34]" if reg is 0
"r[" + reg + "]"
@tRDH = (i) ->
reg = (i >> 11 & 0x1f)
return "h[34]" if reg is 0
"h[" + reg + "]"
@tRT = (i) ->
reg = (i >> 16 & 0x1f)
return "r[34]" if reg is 0
"r[" + reg + "]"
@tRTH = (i) ->
reg = (i >> 16 & 0x1f)
return "h[34]" if reg is 0
"h[" + reg + "]"
@RD = (i) ->
reg = (i >> 11 & 0x1f)
return "~-1" if reg is 0
"r[" + reg + "]"
@RDH = (i) ->
reg = (i >> 11 & 0x1f)
return "~-1" if reg is 0
"h[" + reg + "]"
@uRD = (i) ->
reg = (i >> 11 & 0x1f)
return "~-1" if reg is 0
"(r[" + reg + "]>>>0)"
@uRDH = (i) ->
reg = (i >> 11 & 0x1f)
return "~-1" if reg is 0
"(h[" + reg + "]>>>0)"
@RT = (i) ->
reg = (i >> 16 & 0x1f)
return "~-1" if reg is 0
"r[" + reg + "]"
@RTH = (i) ->
reg = (i >> 16 & 0x1f)
return "~-1" if reg is 0
"h[" + reg + "]"
@uRT = (i) ->
reg = (i >> 16 & 0x1f)
return "~-1" if reg is 0
"(r[" + reg + "]>>>0)"
@uRTH = (i) ->
reg = (i >> 16 & 0x1f)
return "~-1" if reg is 0
"(h[" + reg + "]>>>0)"
@rt = (i) ->
i >> 16 & 0x1f
@offset_imm = (i) ->
i & 0xffff
@soffset_imm = (i) ->
i << 16 >> 16
@setVAddr = (i) ->
"r[38]=" + @RS(i) + "+" + @soffset_imm(i) + ";"
@fn = (i) ->
i & 0x3f
@sa = (i) ->
i >> 6 & 0x1F
@fd = (i) ->
i >> 6 & 0x1F
@sLogic = (i, n) ->
if (@rd(i) is @rs(i))
@tRD(i) + n + "=" + @RT(i) + ";" + @tRDH(i) + "=" + @RD(i) + ">>31;"
else
@tRD(i) + "=" + @RS(i) + n + @RT(i) + ";" + @tRDH(i) + "=" + @RD(i) + ">>31;";
@dLogic = (i, n) ->
if (@rd(i) is @rs(i))
@tRD(i) + n + "=" + @RT(i) + ";" + @tRDH(i) + n + "=" + @RTH(i) + ";"
else
@tRD(i) + "=" + @RS(i) + n + @RT(i) + ";" + @tRDH(i) + "=" + @RSH(i) + n + @RTH(i) + ";"
@virtualToPhysical = (addr) ->
"r[35]=" + addr + ";r[36]=(m.t[r[35]>>>12]<<16)|(r[35]&0xffff);"
#//////////////////////////
#Interpreted opcode helpers
#//////////////////////////
#called function, not compiled
@inter_mtc0 = (r, f, rt, isDelaySlot, pc, cp0, interrupts) ->
#incomplete:
switch f
when consts.CAUSE
cp0[f] &= ~0x300
cp0[f] |= r[rt] & 0x300
# if (((r[rt] & 1)===1) && (cp0[f] & 1)===0) //possible fix over 1964cpp?
interrupts.setException consts.EXC_INT, 0, pc, isDelaySlot if (cp0[consts.CAUSE] & cp0[consts.STATUS] & 0x0000FF00) isnt 0 and (r[rt] & 0x300) isnt 0
#interrupts.processException(pc, isDelaySlot);
when consts.COUNT
cp0[f] = r[rt]
when consts.COMPARE
cp0[consts.CAUSE] &= ~consts.CAUSE_IP8
cp0[f] = r[rt]
when consts.STATUS
if ((r[rt] & consts.EXL) is 0) and ((cp0[f] & consts.EXL) is 1)
if (cp0[consts.CAUSE] & cp0[consts.STATUS] & 0x0000FF00) isnt 0
cp0[f] = r[rt]
interrupts.setException consts.EXC_INT, 0, pc, isDelaySlot
#interrupts.processException(pc, isDelaySlot);
return
if ((r[rt] & consts.IE) is 1) and ((cp0[f] & consts.IE) is 0)
if (cp0[consts.CAUSE] & cp0[consts.STATUS] & 0x0000FF00) isnt 0
cp0[f] = r[rt]
interrupts.setException consts.EXC_INT, 0, pc, isDelaySlot
#interrupts.processException(pc, isDelaySlot);
return
cp0[f] = r[rt]
#tlb:
when consts.BADVADDR, consts.PREVID, consts.RANDOM
break
when consts.INDEX
cp0[f] = r[rt] & 0x8000003F
when consts.ENTRYLO0
cp0[f] = r[rt] & 0x3FFFFFFF
when consts.ENTRYLO1
cp0[f] = r[rt] & 0x3FFFFFFF
when consts.ENTRYHI
cp0[f] = r[rt] & 0xFFFFE0FF
when consts.PAGEMASK
cp0[f] = r[rt] & 0x01FFE000
when consts.WIRED
cp0[f] = r[rt] & 0x1f
cp0[consts.RANDOM] = 0x1f
else
cp0[f] = r[rt]
return
@inter_mult = (r, h, i) ->
res = undefined
r1 = undefined
r2 = undefined
rt32 = undefined
rs32 = r[@rs(i)]
rt32 = r[@rt(i)]
r1 = goog.math.Long.fromBits(rs32, rs32 >> 31)
r2 = goog.math.Long.fromBits(rt32, rt32 >> 31)
res = r1.multiply(r2)
r[32] = res.getLowBits() #lo
h[32] = r[32] >> 31
r[33] = res.getHighBits() #hi
h[33] = r[33] >> 31
return
@inter_multu = (r, h, i) ->
res = undefined
r1 = undefined
r2 = undefined
rt32 = undefined
rs32 = r[@rs(i)]
rt32 = r[@rt(i)]
r1 = goog.math.Long.fromBits(rs32, 0)
r2 = goog.math.Long.fromBits(rt32, 0)
res = r1.multiply(r2)
r[32] = res.getLowBits() #lo
h[32] = r[32] >> 31
r[33] = res.getHighBits() #hi
h[33] = r[33] >> 31
return
# alert('multu: '+r[this.rs(i)]+'*'+r[this.rt(i)]+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_daddi = (r, h, i) ->
rtres = undefined
imm = undefined
rs1 = goog.math.Long.fromBits(r[@rs(i)], h[@rs(i)])
imm = goog.math.Long.fromBits(@soffset_imm(i), @soffset_imm(i) >> 31)
rtres = rs1.add(imm)
r[@rt(i)] = rtres.getLowBits() #lo
h[@rt(i)] = rtres.getHighBits() #hi
return
@inter_daddiu = (r, h, i) ->
rtres = undefined
imm = undefined
rs1 = goog.math.Long.fromBits(r[@rs(i)], h[@rs(i)])
imm = goog.math.Long.fromBits(@soffset_imm(i), @soffset_imm(i) >> 31)
rtres = rs1.add(imm)
r[@rt(i)] = rtres.getLowBits() #lo
h[@rt(i)] = rtres.getHighBits() #hi
return
@inter_dadd = (r, h, i) ->
rdres = undefined
rt1 = undefined
rs1 = goog.math.Long.fromBits(r[@rs(i)], h[@rs(i)])
rt1 = goog.math.Long.fromBits(r[@rt(i)], h[@rt(i)])
rdres = rs1.add(rt1)
r[@rd(i)] = rdres.getLowBits() #lo
h[@rd(i)] = rdres.getHighBits() #hi
return
@inter_daddu = (r, h, i) ->
rdres = undefined
rt1 = undefined
rs1 = goog.math.Long.fromBits(r[@rs(i)], h[@rs(i)])
rt1 = goog.math.Long.fromBits(r[@rt(i)], h[@rt(i)])
rdres = rs1.add(rt1)
r[@rd(i)] = rdres.getLowBits() #lo
h[@rd(i)] = rdres.getHighBits() #hi
return
@inter_div = (r, h, i) ->
if r[@rt(i)] is 0
alert "divide by zero"
return
#todo: handle div by zero
r[32] = r[@rs(i)] / r[@rt(i)] #lo
h[32] = r[32] >> 31 #hi
r[33] = r[@rs(i)] % r[@rt(i)] #lo
h[33] = r[33] >> 31 #hi
return
#alert('div: '+r[this.rs(i)]+'/'+r[this.rt(i)]+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_ddiv = (r, h, i) ->
res = undefined
mod = undefined
rsh32 = undefined
rth32 = undefined
r1 = undefined
r2 = undefined
rt32 = undefined
rs32 = r[@rs(i)]
rt32 = r[@rt(i)]
rsh32 = h[@rs(i)]
rth32 = h[@rt(i)]
r1 = goog.math.Long.fromBits(rs32, rsh32)
r2 = goog.math.Long.fromBits(rt32, rth32)
if r2 is 0
alert "divide by zero"
return
res = r1.div(r2)
mod = r1.modulo(r2)
r[32] = res.getLowBits() #lo
h[32] = res.getHighBits() #hi
r[33] = mod.getLowBits() #lo
h[33] = mod.getHighBits() #hi
return
#alert('ddiv: '+rs64+'/'+rt64+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_divu = (r, h, i) ->
if r[@rt(i)] is 0
alert "divide by zero"
return
#todo: handle div by zero
r[32] = (r[@rs(i)] >>> 0) / (r[@rt(i)] >>> 0) #lo
h[32] = r[32] >> 31 #hi
r[33] = (r[@rs(i)] >>> 0) % (r[@rt(i)] >>> 0) #lo
h[33] = r[33] >> 31 #hi
return
#alert('divu: '+r[this.rs(i)]+'/'+r[this.rt(i)]+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_dmult = (r, h, i) ->
#this is wrong..i think BigInt it will treat hex as unsigned?
delim = undefined
x = undefined
y = undefined
z = undefined
num = undefined
rt64 = undefined
alert "dmult RSh negative:" + h[@rs(i)] if h[@rs(i)] < 0
alert "dmult RTh negative:" + h[@rt(i)] if h[@rt(i)] < 0
rs64 = "0x" + String(dec2hex(h[@rs(i)])) + String(dec2hex(r[@rs(i)]))
rt64 = "0x" + String(dec2hex(h[@rt(i)])) + String(dec2hex(r[@rt(i)]))
x = new BigInt(rs64)
y = new BigInt(rt64)
z = bigint_mul(x, y)
num = z.toStringBase(16)
alert "dmult:" + num if num[0] is "-"
if num.length > 24
delim = num.length - 24
h[33] = ("0x" + num.substr(0, delim)) >>> 0 # hi of HIREG
r[33] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of HIREG
h[32] = ("0x" + num.substr(delim + 8, 8)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim + 16, 8)) >>> 0 # lo of LOREG
else if num.length > 16
delim = num.length - 16
h[33] = 0 # hi of HIREG
r[33] = ("0x" + num.substr(0, delim)) >>> 0 # lo of HIREG
h[32] = ("0x" + num.substr(delim, 8)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim + 8, 8)) >>> 0 # lo of LOREG
else if num.length > 8
delim = num.length - 8
h[33] = 0 # hi of HIREG
r[33] = 0 # lo of HIREG
h[32] = ("0x" + num.substr(0, delim)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of LOREG
else
delim = num.length
h[33] = 0 # hi of HIREG
r[33] = 0 # lo of HIREG
h[32] = 0 # hi of LOREG
r[32] = ("0x" + num.substr(0, delim)) >>> 0 # lo of LOREG
return
#alert('dmult: '+rs64+'*'+rt64+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_dmultu = (r, h, i) ->
#Attax demo
delim = undefined
x = undefined
y = undefined
z = undefined
num = undefined
rt64 = undefined
rs64 = "0x0" + String(dec2hex(h[@rs(i)])) + String(dec2hex(r[@rs(i)]))
rt64 = "0x0" + String(dec2hex(h[@rt(i)])) + String(dec2hex(r[@rt(i)]))
x = new BigInt(rs64)
y = new BigInt(rt64)
z = bigint_mul(x, y)
num = z.toStringBase(16)
alert "dmultu:" + num if num[0] is "-"
if num.length > 24
delim = num.length - 24
h[33] = ("0x" + num.substr(0, delim)) >>> 0 # hi of HIREG
r[33] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of HIREG
h[32] = ("0x" + num.substr(delim + 8, 8)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim + 16, 8)) >>> 0 # lo of LOREG
else if num.length > 16
delim = num.length - 16
h[33] = 0 # hi of HIREG
r[33] = ("0x" + num.substr(0, delim)) >>> 0 # lo of HIREG
h[32] = ("0x" + num.substr(delim, 8)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim + 8, 8)) >>> 0 # lo of LOREG
else if num.length > 8
delim = num.length - 8
h[33] = 0 # hi of HIREG
r[33] = 0 # lo of HIREG
h[32] = ("0x" + num.substr(0, delim)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of LOREG
else
delim = num.length
h[33] = 0 # hi of HIREG
r[33] = 0 # lo of HIREG
h[32] = 0 # hi of LOREG
r[32] = ("0x" + num.substr(0, delim)) >>> 0 # lo of LOREG
return
#alert('dmultu: '+rs64+'*'+rt64+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_ddivu = (r, h, i) ->
delim = undefined
x = undefined
y = undefined
z = undefined
num = undefined
rt64 = undefined
rs64 = "0x0" + String(dec2hex(h[@rs(i)])) + String(dec2hex(r[@rs(i)]))
rt64 = "0x0" + String(dec2hex(h[@rt(i)])) + String(dec2hex(r[@rt(i)]))
x = new BigInt(rs64)
y = new BigInt(rt64)
z = bigint_div(x, y)
unless z
r[32] = 0
h[32] = 0
else
num = z.toStringBase(16)
alert "ddivu:" + num if num[0] is "-"
if num.length > 8
delim = num.length - 8
h[32] = ("0x" + num.substr(0, delim)) >>> 0 # hi of LOREG
r[32] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of LOREG
else
delim = num.length
h[32] = 0 # hi of LOREG
r[32] = ("0x" + num.substr(0, delim)) >>> 0 # lo of LOREG
#mod
z = bigint_mod(x, y)
num = z.toStringBase(16)
if num.length > 8
delim = num.length - 8
h[33] = ("0x" + num.substr(0, delim)) >>> 0 # hi of LOREG
r[33] = ("0x" + num.substr(delim, 8)) >>> 0 # lo of LOREG
else
delim = num.length
h[33] = 0 # hi of LOREG
r[33] = ("0x" + num.substr(0, delim)) >>> 0 # lo of LOREG
return
#alert('ddivu: '+rs64+'/'+rt64+'='+dec2hex(h[33]) +' '+dec2hex(r[33])+' '+dec2hex(h[32])+' '+dec2hex(r[32]));
@inter_r4300i_C_cond_fmt_s = (instruction, cp1Con, cp1_f) ->
fcFS32 = undefined
fcFT32 = undefined
less = undefined
equal = undefined
unordered = undefined
cond = undefined
cond0 = undefined
cond1 = undefined
cond2 = undefined
cond3 = undefined
#CHK_ODD_FPR_2_REG(RD_FS, RT_FT);
cond0 = (instruction) & 0x1
cond1 = (instruction >> 1) & 0x1
cond2 = (instruction >> 2) & 0x1
cond3 = (instruction >> 3) & 0x1
fcFS32 = cp1_f[@FS32ArrayView(instruction)]
fcFT32 = cp1_f[@FT32ArrayView(instruction)]
if isNaN(fcFS32) or isNaN(fcFT32)
less = false
equal = false
unordered = true
#Fire invalid operation exception
return if cond3 isnt 0
else
less = (fcFS32 < fcFT32)
equal = (fcFS32 is fcFT32)
unordered = false
cond = ((cond0 and unordered) or (cond1 and equal) or (cond2 and less))
cp1Con[31] &= ~consts.COP1_CONDITION_BIT
cp1Con[31] |= consts.COP1_CONDITION_BIT if cond
return
@inter_r4300i_C_cond_fmt_d = (instruction, cp1Con, cp1_f64) ->
fcFS64 = undefined
fcFT64 = undefined
less = undefined
equal = undefined
unordered = undefined
cond = undefined
cond0 = undefined
cond1 = undefined
cond2 = undefined
cond3 = undefined
# CHK_ODD_FPR_2_REG(RD_FS, RT_FT);
cond0 = (instruction) & 0x1
cond1 = (instruction >> 1) & 0x1
cond2 = (instruction >> 2) & 0x1
cond3 = (instruction >> 3) & 0x1
fcFS64 = cp1_f64[@FS64ArrayView(instruction)]
fcFT64 = cp1_f64[@FT64ArrayView(instruction)]
if isNaN(fcFS64) or isNaN(fcFT64)
less = false
equal = false
unordered = true
#Fire invalid operation exception
return if cond3 isnt 0
else
less = (fcFS64 < fcFT64)
equal = (fcFS64 is fcFT64)
unordered = false
cond = ((cond0 and unordered) or (cond1 and equal) or (cond2 and less))
cp1Con[31] &= ~consts.COP1_CONDITION_BIT
cp1Con[31] |= consts.COP1_CONDITION_BIT if cond
return
@writeTLBEntry = (tlb, cp0) ->
g = cp0[consts.ENTRYLO0] & cp0[consts.ENTRYLO1] & consts.TLBLO_G
tlb.pageMask = cp0[consts.PAGEMASK] >>> 0
tlb.entryLo1 = (cp0[consts.ENTRYLO1] | g) >>> 0
tlb.entryLo0 = (cp0[consts.ENTRYLO0] | g) >>> 0
tlb.myHiMask = ((~tlb.pageMask >>> 0) & consts.TLBHI_VPN2MASK) >>> 0
tlb.entryHi = ((cp0[consts.ENTRYHI]>>>0) & (~cp0[consts.PAGEMASK] >>> 0)) >>> 0
switch tlb.pageMask
when 0x00000000 then tlb.loCompare = 0x00001000 #4k
when 0x00006000 then tlb.loCompare = 0x00004000 #16k
when 0x0001e000 then tlb.loCompare = 0x00010000 #64k
when 0x0007e000 then tlb.loCompare = 0x00040000 #256k
when 0x001fe000 then tlb.loCompare = 0x00100000 #1M
when 0x007fe000 then tlb.loCompare = 0x00400000 #4M
when 0x01ffe000 then tlb.loCompare = 0x01000000 #16M
else console.log "ERROR: tlbwi - invalid page size" + tlb.pageMask
@newtlb = true
return
@buildTLBHelper = (start, end, entry, mask, clear) ->
i = start>>>12
lend = end>>>12
if (clear is true) #clear unconditionally or if (entry & 3)? If so, why?
while i < lend
@core.memory.t[i] = (i & 0x1ffff) >>> 4
i++
else #if (entry & 0x3) #why?
realAddress = (0x80000000 | (((entry << 6)>>>0) & (mask >>> 1))) >>> 0
while i < lend
real = (realAddress + (i << 12) - start) & 0x1fffffff
@core.memory.t[i] = real >>> 16
i++
return
@buildTLB = (tlb, clear) ->
#calculate the mapped address range that this TLB entry is mapping
lowest = (tlb.entryHi & 0xffffff00) >>> 0 #Don't support ASID field
middle = (lowest + tlb.loCompare) >>> 0
highest = (lowest + tlb.loCompare * 2) >>> 0
@buildTLBHelper lowest, middle, tlb.entryLo0, tlb.myHiMask, clear
@buildTLBHelper middle, highest, tlb.entryLo1, tlb.myHiMask, clear
return
@refreshTLB = (tlb, cp0) ->
@buildTLB tlb, true if tlb.valid is 1 #clear old tlb
@writeTLBEntry tlb, cp0
tlb.valid = 0
tlb.valid = 1 if (cp0[consts.ENTRYLO1] & consts.TLBLO_V) or (cp0[consts.ENTRYLO0] & consts.TLBLO_V)
@buildTLB tlb if tlb.valid is 1
return
@inter_tlbwi = (index, tlb, cp0) ->
if index < 0 or index > 31
console.log "ERROR: tlbwi received an invalid index=%08X", index
return
@refreshTLB tlb[index], cp0
return
@inter_tlbp = (tlb, cp0) ->
cp0[consts.INDEX] |= 0x80000000 #initially set high-order bit
idx = 0
while idx < 31
if (tlb[idx].entryHi & tlb[idx].myHiMask) is (cp0[consts.ENTRYHI] & tlb[idx].myHiMask)
if (tlb[idx].entryLo0 & consts.TLBLO_G & tlb[idx].entryLo1) or (tlb[idx].entryHi & consts.TLBHI_PIDMASK) is (cp0[consts.ENTRYHI] & consts.TLBHI_PIDMASK)
cp0[consts.INDEX] = idx
break
idx++
return
@inter_tlbr = (tlb, cp0) ->
index = cp0[consts.INDEX] & 0x7FFFFFFF
if index < 0 or index > 31
console.log "ERROR: tlbr received an invalid index=%08X", index
return
cp0[consts.PAGEMASK] = tlb[index].pageMask
cp0[consts.ENTRYHI] = tlb[index].entryHi
cp0[consts.ENTRYHI] &= (~tlb[index].pageMask >>> 0)
cp0[consts.ENTRYLO1] = tlb[index].entryLo1
cp0[consts.ENTRYLO0] = tlb[index].entryLo0
return
this
#hack global space until we export classes properly
#node.js uses exports; browser uses this (window)
root = exports ? self
root.C1964jsHelpers = C1964jsHelpers
#print out a hex number
root.dec2hex = (u) ->
"use strict"
d = undefined
h = undefined
hD = "0123456789ABCDEF"
d = u
h = hD.substr(d & 15, 1)
loop
d >>= 4
d &= 0x0fffffff
h = hD.substr(d & 15, 1) + h
break unless d > 15
h