| | ARMCoreArm = function (cpu) { |
| | this.cpu = cpu; |
| |
|
| | this.addressingMode23Immediate = [ |
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] -= offset; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] += offset; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | return addr = gprs[rn] - offset; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn] - offset; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | return addr = gprs[rn] + offset; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, offset, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn] + offset; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null, |
| | ]; |
| |
|
| | this.addressingMode23Register = [ |
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] -= gprs[rm]; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] += gprs[rm]; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | return gprs[rn] - gprs[rm]; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn] - gprs[rm]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn] + gprs[rm]; |
| | return addr; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, rm, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn] + gprs[rm]; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null |
| | ]; |
| |
|
| | this.addressingMode2RegisterShifted = [ |
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | shiftOp(); |
| | gprs[rn] -= cpu.shifterOperand; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | var addr = gprs[rn]; |
| | if (!condOp || condOp()) { |
| | shiftOp(); |
| | gprs[rn] += cpu.shifterOperand; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| | |
| | null, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | shiftOp(); |
| | return gprs[rn] - cpu.shifterOperand; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | shiftOp(); |
| | var addr = gprs[rn] - cpu.shifterOperand; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writesPC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null, |
| |
|
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | shiftOp(); |
| | return gprs[rn] + cpu.shifterOperand; |
| | }; |
| | address.writesPC = false; |
| | return address; |
| | }, |
| |
|
| | |
| | function(rn, shiftOp, condOp) { |
| | var gprs = cpu.gprs; |
| | var address = function() { |
| | shiftOp(); |
| | var addr = gprs[rn] + cpu.shifterOperand; |
| | if (!condOp || condOp()) { |
| | gprs[rn] = addr; |
| | } |
| | return addr; |
| | }; |
| | address.writePC = rn == cpu.PC; |
| | return address; |
| | }, |
| |
|
| | null, |
| | null, |
| | ]; |
| | } |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1ASR = function(rs, rm) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | ++cpu.cycles; |
| | var shift = gprs[rs]; |
| | if (rs == cpu.PC) { |
| | shift += 4; |
| | } |
| | shift &= 0xFF; |
| | var shiftVal = gprs[rm]; |
| | if (rm == cpu.PC) { |
| | shiftVal += 4; |
| | } |
| | if (shift == 0) { |
| | cpu.shifterOperand = shiftVal; |
| | cpu.shifterCarryOut = cpu.cpsrC; |
| | } else if (shift < 32) { |
| | cpu.shifterOperand = shiftVal >> shift; |
| | cpu.shifterCarryOut = shiftVal & (1 << (shift - 1)); |
| | } else if (gprs[rm] >> 31) { |
| | cpu.shifterOperand = 0xFFFFFFFF; |
| | cpu.shifterCarryOut = 0x80000000; |
| | } else { |
| | cpu.shifterOperand = 0; |
| | cpu.shifterCarryOut = 0; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1Immediate = function(immediate) { |
| | var cpu = this.cpu; |
| | return function() { |
| | cpu.shifterOperand = immediate; |
| | cpu.shifterCarryOut = cpu.cpsrC; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1ImmediateRotate = function(immediate, rotate) { |
| | var cpu = this.cpu; |
| | return function() { |
| | cpu.shifterOperand = (immediate >>> rotate) | (immediate << (32 - rotate)); |
| | cpu.shifterCarryOut = cpu.shifterOperand >> 31; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1LSL = function(rs, rm) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | ++cpu.cycles; |
| | var shift = gprs[rs]; |
| | if (rs == cpu.PC) { |
| | shift += 4; |
| | } |
| | shift &= 0xFF; |
| | var shiftVal = gprs[rm]; |
| | if (rm == cpu.PC) { |
| | shiftVal += 4; |
| | } |
| | if (shift == 0) { |
| | cpu.shifterOperand = shiftVal; |
| | cpu.shifterCarryOut = cpu.cpsrC; |
| | } else if (shift < 32) { |
| | cpu.shifterOperand = shiftVal << shift; |
| | cpu.shifterCarryOut = shiftVal & (1 << (32 - shift)); |
| | } else if (shift == 32) { |
| | cpu.shifterOperand = 0; |
| | cpu.shifterCarryOut = shiftVal & 1; |
| | } else { |
| | cpu.shifterOperand = 0; |
| | cpu.shifterCarryOut = 0; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1LSR = function(rs, rm) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | ++cpu.cycles; |
| | var shift = gprs[rs]; |
| | if (rs == cpu.PC) { |
| | shift += 4; |
| | } |
| | shift &= 0xFF; |
| | var shiftVal = gprs[rm]; |
| | if (rm == cpu.PC) { |
| | shiftVal += 4; |
| | } |
| | if (shift == 0) { |
| | cpu.shifterOperand = shiftVal; |
| | cpu.shifterCarryOut = cpu.cpsrC; |
| | } else if (shift < 32) { |
| | cpu.shifterOperand = shiftVal >>> shift; |
| | cpu.shifterCarryOut = shiftVal & (1 << (shift - 1)); |
| | } else if (shift == 32) { |
| | cpu.shifterOperand = 0; |
| | cpu.shifterCarryOut = shiftVal >> 31; |
| | } else { |
| | cpu.shifterOperand = 0; |
| | cpu.shifterCarryOut = 0; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode1ROR = function(rs, rm) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | ++cpu.cycles; |
| | var shift = gprs[rs]; |
| | if (rs == cpu.PC) { |
| | shift += 4; |
| | } |
| | shift &= 0xFF; |
| | var shiftVal = gprs[rm]; |
| | if (rm == cpu.PC) { |
| | shiftVal += 4; |
| | } |
| | var rotate = shift & 0x1F; |
| | if (shift == 0) { |
| | cpu.shifterOperand = shiftVal; |
| | cpu.shifterCarryOut = cpu.cpsrC; |
| | } else if (rotate) { |
| | cpu.shifterOperand = (gprs[rm] >>> rotate) | (gprs[rm] << (32 - rotate)); |
| | cpu.shifterCarryOut = shiftVal & (1 << (rotate - 1)); |
| | } else { |
| | cpu.shifterOperand = shiftVal; |
| | cpu.shifterCarryOut = shiftVal >> 31; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode23Immediate = function(instruction, immediate, condOp) { |
| | var rn = (instruction & 0x000F0000) >> 16; |
| | return this.addressingMode23Immediate[(instruction & 0x01A00000) >> 21](rn, immediate, condOp); |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode23Register = function(instruction, rm, condOp) { |
| | var rn = (instruction & 0x000F0000) >> 16; |
| | return this.addressingMode23Register[(instruction & 0x01A00000) >> 21](rn, rm, condOp); |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode2RegisterShifted = function(instruction, shiftOp, condOp) { |
| | var rn = (instruction & 0x000F0000) >> 16; |
| | return this.addressingMode2RegisterShifted[(instruction & 0x01A00000) >> 21](rn, shiftOp, condOp); |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode4 = function(immediate, rn) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | var addr = gprs[rn] + immediate; |
| | return addr; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAddressingMode4Writeback = function(immediate, offset, rn, overlap) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function(writeInitial) { |
| | var addr = gprs[rn] + immediate; |
| | if (writeInitial && overlap) { |
| | cpu.mmu.store32(gprs[rn] + immediate - 4, gprs[rn]); |
| | } |
| | gprs[rn] += offset; |
| | return addr; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructADC = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var shifterOperand = (cpu.shifterOperand >>> 0) + !!cpu.cpsrC; |
| | gprs[rd] = (gprs[rn] >>> 0) + shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructADCS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var shifterOperand = (cpu.shifterOperand >>> 0) + !!cpu.cpsrC; |
| | var d = (gprs[rn] >>> 0) + shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = d > 0xFFFFFFFF; |
| | cpu.cpsrV = (gprs[rn] >> 31) == (shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (d >> 31) && |
| | (shifterOperand >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructADD = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = (gprs[rn] >>> 0) + (cpu.shifterOperand >>> 0); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructADDS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var d = (gprs[rn] >>> 0) + (cpu.shifterOperand >>> 0); |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = d > 0xFFFFFFFF; |
| | cpu.cpsrV = (gprs[rn] >> 31) == (cpu.shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (d >> 31) && |
| | (cpu.shifterOperand >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructAND = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] & cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructANDS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] & cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructB = function(immediate, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | gprs[cpu.PC] += immediate; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructBIC = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] & ~cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructBICS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] & ~cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructBL = function(immediate, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | gprs[cpu.LR] = gprs[cpu.PC] - 4; |
| | gprs[cpu.PC] += immediate; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructBX = function(rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | cpu.switchExecMode(gprs[rm] & 0x00000001); |
| | gprs[cpu.PC] = gprs[rm] & 0xFFFFFFFE; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructCMN = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var aluOut = (gprs[rn] >>> 0) + (cpu.shifterOperand >>> 0); |
| | cpu.cpsrN = aluOut >> 31; |
| | cpu.cpsrZ = !(aluOut & 0xFFFFFFFF); |
| | cpu.cpsrC = aluOut > 0xFFFFFFFF; |
| | cpu.cpsrV = (gprs[rn] >> 31) == (cpu.shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (aluOut >> 31) && |
| | (cpu.shifterOperand >> 31) != (aluOut >> 31); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructCMP = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var aluOut = gprs[rn] - cpu.shifterOperand; |
| | cpu.cpsrN = aluOut >> 31; |
| | cpu.cpsrZ = !(aluOut & 0xFFFFFFFF); |
| | cpu.cpsrC = (gprs[rn] >>> 0) >= (cpu.shifterOperand >>> 0); |
| | cpu.cpsrV = (gprs[rn] >> 31) != (cpu.shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (aluOut >> 31); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructEOR = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] ^ cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructEORS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] ^ cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDM = function(rs, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | var mmu = cpu.mmu; |
| | return function() { |
| | mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(false); |
| | var total = 0; |
| | var m, i; |
| | for (m = rs, i = 0; m; m >>= 1, ++i) { |
| | if (m & 1) { |
| | gprs[i] = mmu.load32(addr & 0xFFFFFFFC); |
| | addr += 4; |
| | ++total; |
| | } |
| | } |
| | mmu.waitMulti32(addr, total); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDMS = function(rs, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | var mmu = cpu.mmu; |
| | return function() { |
| | mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(false); |
| | var total = 0; |
| | var mode = cpu.mode; |
| | cpu.switchMode(cpu.MODE_SYSTEM); |
| | var m, i; |
| | for (m = rs, i = 0; m; m >>= 1, ++i) { |
| | if (m & 1) { |
| | gprs[i] = mmu.load32(addr & 0xFFFFFFFC); |
| | addr += 4; |
| | ++total; |
| | } |
| | } |
| | cpu.switchMode(mode); |
| | mmu.waitMulti32(addr, total); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDR = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(); |
| | gprs[rd] = cpu.mmu.load32(addr); |
| | cpu.mmu.wait32(addr); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDRB = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(); |
| | gprs[rd] = cpu.mmu.loadU8(addr); |
| | cpu.mmu.wait(addr); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDRH = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(); |
| | gprs[rd] = cpu.mmu.loadU16(addr); |
| | cpu.mmu.wait(addr); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDRSB = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(); |
| | gprs[rd] = cpu.mmu.load8(addr); |
| | cpu.mmu.wait(addr); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructLDRSH = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var addr = address(); |
| | gprs[rd] = cpu.mmu.load16(addr); |
| | cpu.mmu.wait(addr); |
| | ++cpu.cycles; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMLA = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(rs); |
| | if ((gprs[rm] & 0xFFFF0000) && (gprs[rs] & 0xFFFF0000)) { |
| | |
| | var hi = ((gprs[rm] & 0xFFFF0000) * gprs[rs]) & 0xFFFFFFFF; |
| | var lo = ((gprs[rm] & 0x0000FFFF) * gprs[rs]) & 0xFFFFFFFF; |
| | gprs[rd] = (hi + lo + gprs[rn]) & 0xFFFFFFFF; |
| | } else { |
| | gprs[rd] = gprs[rm] * gprs[rs] + gprs[rn]; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMLAS = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(rs); |
| | if ((gprs[rm] & 0xFFFF0000) && (gprs[rs] & 0xFFFF0000)) { |
| | |
| | var hi = ((gprs[rm] & 0xFFFF0000) * gprs[rs]) & 0xFFFFFFFF; |
| | var lo = ((gprs[rm] & 0x0000FFFF) * gprs[rs]) & 0xFFFFFFFF; |
| | gprs[rd] = (hi + lo + gprs[rn]) & 0xFFFFFFFF; |
| | } else { |
| | gprs[rd] = gprs[rm] * gprs[rs] + gprs[rn]; |
| | } |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMOV = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMOVS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMRS = function(rd, r, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | if (r) { |
| | gprs[rd] = cpu.spsr; |
| | } else { |
| | gprs[rd] = cpu.packCPSR(); |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMSR = function(rm, r, instruction, immediate, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | var c = instruction & 0x00010000; |
| | |
| | |
| | var f = instruction & 0x00080000; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | var operand; |
| | if (instruction & 0x02000000) { |
| | operand = immediate; |
| | } else { |
| | operand = gprs[rm]; |
| | } |
| | var mask = (c ? 0x000000FF : 0x00000000) | |
| | |
| | |
| | (f ? 0xFF000000 : 0x00000000); |
| |
|
| | if (r) { |
| | mask &= cpu.USER_MASK | cpu.PRIV_MASK | cpu.STATE_MASK; |
| | cpu.spsr = (cpu.spsr & ~mask) | (operand & mask); |
| | } else { |
| | if (mask & cpu.USER_MASK) { |
| | cpu.cpsrN = operand >> 31; |
| | cpu.cpsrZ = operand & 0x40000000; |
| | cpu.cpsrC = operand & 0x20000000; |
| | cpu.cpsrV = operand & 0x10000000; |
| | } |
| | if (cpu.mode != cpu.MODE_USER && (mask & cpu.PRIV_MASK)) { |
| | cpu.switchMode((operand & 0x0000000F) | 0x00000010); |
| | cpu.cpsrI = operand & 0x00000080; |
| | cpu.cpsrF = operand & 0x00000040; |
| | } |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMUL = function(rd, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.mmu.waitMul(gprs[rs]); |
| | if ((gprs[rm] & 0xFFFF0000) && (gprs[rs] & 0xFFFF0000)) { |
| | |
| | var hi = ((gprs[rm] & 0xFFFF0000) * gprs[rs]) | 0; |
| | var lo = ((gprs[rm] & 0x0000FFFF) * gprs[rs]) | 0; |
| | gprs[rd] = hi + lo; |
| | } else { |
| | gprs[rd] = gprs[rm] * gprs[rs]; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMULS = function(rd, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.mmu.waitMul(gprs[rs]); |
| | if ((gprs[rm] & 0xFFFF0000) && (gprs[rs] & 0xFFFF0000)) { |
| | |
| | var hi = ((gprs[rm] & 0xFFFF0000) * gprs[rs]) | 0; |
| | var lo = ((gprs[rm] & 0x0000FFFF) * gprs[rs]) | 0; |
| | gprs[rd] = hi + lo; |
| | } else { |
| | gprs[rd] = gprs[rm] * gprs[rs]; |
| | } |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMVN = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = ~cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructMVNS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = ~cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructORR = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] | cpu.shifterOperand; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructORRS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] | cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !(gprs[rd] & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | } |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructRSB = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = cpu.shifterOperand - gprs[rn]; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructRSBS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var d = cpu.shifterOperand - gprs[rn]; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = (cpu.shifterOperand >>> 0) >= (gprs[rn] >>> 0); |
| | cpu.cpsrV = (cpu.shifterOperand >> 31) != (gprs[rn] >> 31) && |
| | (cpu.shifterOperand >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructRSC = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var n = (gprs[rn] >>> 0) + !cpu.cpsrC; |
| | gprs[rd] = (cpu.shifterOperand >>> 0) - n; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructRSCS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var n = (gprs[rn] >>> 0) + !cpu.cpsrC; |
| | var d = (cpu.shifterOperand >>> 0) - n; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = (cpu.shifterOperand >>> 0) >= (d >>> 0); |
| | cpu.cpsrV = (cpu.shifterOperand >> 31) != (n >> 31) && |
| | (cpu.shifterOperand >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSBC = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var shifterOperand = (cpu.shifterOperand >>> 0) + !cpu.cpsrC; |
| | gprs[rd] = (gprs[rn] >>> 0) - shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSBCS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var shifterOperand = (cpu.shifterOperand >>> 0) + !cpu.cpsrC; |
| | var d = (gprs[rn] >>> 0) - shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = (gprs[rn] >>> 0) >= (d >>> 0); |
| | cpu.cpsrV = (gprs[rn] >> 31) != (shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSMLAL = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.cycles += 2; |
| | cpu.mmu.waitMul(rs); |
| | var hi = (gprs[rm] & 0xFFFF0000) * gprs[rs]; |
| | var lo = (gprs[rm] & 0x0000FFFF) * gprs[rs]; |
| | var carry = (gprs[rn] >>> 0) + hi + lo; |
| | gprs[rn] = carry; |
| | gprs[rd] += Math.floor(carry * SHIFT_32); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSMLALS = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.cycles += 2; |
| | cpu.mmu.waitMul(rs); |
| | var hi = (gprs[rm] & 0xFFFF0000) * gprs[rs]; |
| | var lo = (gprs[rm] & 0x0000FFFF) * gprs[rs]; |
| | var carry = (gprs[rn] >>> 0) + hi + lo; |
| | gprs[rn] = carry; |
| | gprs[rd] += Math.floor(carry * SHIFT_32); |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !((gprs[rd] & 0xFFFFFFFF) || (gprs[rn] & 0xFFFFFFFF)); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSMULL = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(gprs[rs]); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >> 0) * (gprs[rs] >> 0); |
| | var lo = ((gprs[rm] & 0x0000FFFF) >> 0) * (gprs[rs] >> 0); |
| | gprs[rn] = ((hi & 0xFFFFFFFF) + (lo & 0xFFFFFFFF)) & 0xFFFFFFFF; |
| | gprs[rd] = Math.floor(hi * SHIFT_32 + lo * SHIFT_32); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSMULLS = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(gprs[rs]); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >> 0) * (gprs[rs] >> 0); |
| | var lo = ((gprs[rm] & 0x0000FFFF) >> 0) * (gprs[rs] >> 0); |
| | gprs[rn] = ((hi & 0xFFFFFFFF) + (lo & 0xFFFFFFFF)) & 0xFFFFFFFF; |
| | gprs[rd] = Math.floor(hi * SHIFT_32 + lo * SHIFT_32); |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !((gprs[rd] & 0xFFFFFFFF) || (gprs[rn] & 0xFFFFFFFF)); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSTM = function(rs, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | var mmu = cpu.mmu; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | mmu.wait32(gprs[cpu.PC]); |
| | var addr = address(true); |
| | var total = 0; |
| | var m, i; |
| | for (m = rs, i = 0; m; m >>= 1, ++i) { |
| | if (m & 1) { |
| | mmu.store32(addr, gprs[i]); |
| | addr += 4; |
| | ++total; |
| | } |
| | } |
| | mmu.waitMulti32(addr, total); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSTMS = function(rs, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | var mmu = cpu.mmu; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | mmu.wait32(gprs[cpu.PC]); |
| | var mode = cpu.mode; |
| | var addr = address(true); |
| | var total = 0; |
| | var m, i; |
| | cpu.switchMode(cpu.MODE_SYSTEM); |
| | for (m = rs, i = 0; m; m >>= 1, ++i) { |
| | if (m & 1) { |
| | mmu.store32(addr, gprs[i]); |
| | addr += 4; |
| | ++total; |
| | } |
| | } |
| | cpu.switchMode(mode); |
| | mmu.waitMulti32(addr, total); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSTR = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | var addr = address(); |
| | cpu.mmu.store32(addr, gprs[rd]); |
| | cpu.mmu.wait32(addr); |
| | cpu.mmu.wait32(gprs[cpu.PC]); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSTRB = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | var addr = address(); |
| | cpu.mmu.store8(addr, gprs[rd]); |
| | cpu.mmu.wait(addr); |
| | cpu.mmu.wait32(gprs[cpu.PC]); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSTRH = function(rd, address, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | var addr = address(); |
| | cpu.mmu.store16(addr, gprs[rd]); |
| | cpu.mmu.wait(addr); |
| | cpu.mmu.wait32(gprs[cpu.PC]); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSUB = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | gprs[rd] = gprs[rn] - cpu.shifterOperand; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSUBS = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var d = gprs[rn] - cpu.shifterOperand; |
| | if (rd == cpu.PC && cpu.hasSPSR()) { |
| | cpu.unpackCPSR(cpu.spsr); |
| | } else { |
| | cpu.cpsrN = d >> 31; |
| | cpu.cpsrZ = !(d & 0xFFFFFFFF); |
| | cpu.cpsrC = (gprs[rn] >>> 0) >= (cpu.shifterOperand >>> 0); |
| | cpu.cpsrV = (gprs[rn] >> 31) != (cpu.shifterOperand >> 31) && |
| | (gprs[rn] >> 31) != (d >> 31); |
| | } |
| | gprs[rd] = d; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSWI = function(immediate, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | if (condOp && !condOp()) { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | return; |
| | } |
| | cpu.irq.swi32(immediate); |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSWP = function(rd, rn, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.mmu.wait32(gprs[rn]); |
| | cpu.mmu.wait32(gprs[rn]); |
| | var d = cpu.mmu.load32(gprs[rn]); |
| | cpu.mmu.store32(gprs[rn], gprs[rm]); |
| | gprs[rd] = d; |
| | ++cpu.cycles; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructSWPB = function(rd, rn, rm, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.mmu.wait(gprs[rn]); |
| | cpu.mmu.wait(gprs[rn]); |
| | var d = cpu.mmu.load8(gprs[rn]); |
| | cpu.mmu.store8(gprs[rn], gprs[rm]); |
| | gprs[rd] = d; |
| | ++cpu.cycles; |
| | } |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructTEQ = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var aluOut = gprs[rn] ^ cpu.shifterOperand; |
| | cpu.cpsrN = aluOut >> 31; |
| | cpu.cpsrZ = !(aluOut & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructTST = function(rd, rn, shiftOp, condOp) { |
| | var cpu = this.cpu; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | shiftOp(); |
| | var aluOut = gprs[rn] & cpu.shifterOperand; |
| | cpu.cpsrN = aluOut >> 31; |
| | cpu.cpsrZ = !(aluOut & 0xFFFFFFFF); |
| | cpu.cpsrC = cpu.shifterCarryOut; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructUMLAL = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.cycles += 2; |
| | cpu.mmu.waitMul(rs); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >>> 0) * (gprs[rs] >>> 0); |
| | var lo = (gprs[rm] & 0x0000FFFF) * (gprs[rs] >>> 0); |
| | var carry = (gprs[rn] >>> 0) + hi + lo; |
| | gprs[rn] = carry; |
| | gprs[rd] += carry * SHIFT_32; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructUMLALS = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | cpu.cycles += 2; |
| | cpu.mmu.waitMul(rs); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >>> 0) * (gprs[rs] >>> 0); |
| | var lo = (gprs[rm] & 0x0000FFFF) * (gprs[rs] >>> 0); |
| | var carry = (gprs[rn] >>> 0) + hi + lo; |
| | gprs[rn] = carry; |
| | gprs[rd] += carry * SHIFT_32; |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !((gprs[rd] & 0xFFFFFFFF) || (gprs[rn] & 0xFFFFFFFF)); |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructUMULL = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(gprs[rs]); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >>> 0) * (gprs[rs] >>> 0); |
| | var lo = ((gprs[rm] & 0x0000FFFF) >>> 0) * (gprs[rs] >>> 0); |
| | gprs[rn] = ((hi & 0xFFFFFFFF) + (lo & 0xFFFFFFFF)) & 0xFFFFFFFF; |
| | gprs[rd] = (hi * SHIFT_32 + lo * SHIFT_32) >>> 0; |
| | }; |
| | }; |
| |
|
| | ARMCoreArm.prototype.constructUMULLS = function(rd, rn, rs, rm, condOp) { |
| | var cpu = this.cpu; |
| | var SHIFT_32 = 1/0x100000000; |
| | var gprs = cpu.gprs; |
| | return function() { |
| | cpu.mmu.waitPrefetch32(gprs[cpu.PC]); |
| | if (condOp && !condOp()) { |
| | return; |
| | } |
| | ++cpu.cycles; |
| | cpu.mmu.waitMul(gprs[rs]); |
| | var hi = ((gprs[rm] & 0xFFFF0000) >>> 0) * (gprs[rs] >>> 0); |
| | var lo = ((gprs[rm] & 0x0000FFFF) >>> 0) * (gprs[rs] >>> 0); |
| | gprs[rn] = ((hi & 0xFFFFFFFF) + (lo & 0xFFFFFFFF)) & 0xFFFFFFFF; |
| | gprs[rd] = (hi * SHIFT_32 + lo * SHIFT_32) >>> 0; |
| | cpu.cpsrN = gprs[rd] >> 31; |
| | cpu.cpsrZ = !((gprs[rd] & 0xFFFFFFFF) || (gprs[rn] & 0xFFFFFFFF)); |
| | }; |
| | }; |
| |
|