1570 lines
36 KiB
JavaScript
1570 lines
36 KiB
JavaScript
ARMCoreArm = function (cpu) {
|
|
this.cpu = cpu;
|
|
|
|
this.addressingMode23Immediate = [
|
|
// 000x0
|
|
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;
|
|
},
|
|
|
|
// 000xW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// 00Ux0
|
|
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;
|
|
},
|
|
|
|
// 00UxW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// 0P0x0
|
|
function(rn, offset, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
return addr = gprs[rn] - offset;
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// 0P0xW
|
|
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,
|
|
|
|
// 0PUx0
|
|
function(rn, offset, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
return addr = gprs[rn] + offset;
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// 0PUxW
|
|
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 = [
|
|
// I00x0
|
|
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;
|
|
},
|
|
|
|
// I00xW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// I0Ux0
|
|
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;
|
|
},
|
|
|
|
// I0UxW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// IP0x0
|
|
function(rn, rm, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
return gprs[rn] - gprs[rm];
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// IP0xW
|
|
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,
|
|
|
|
// IPUx0
|
|
function(rn, rm, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
var addr = gprs[rn] + gprs[rm];
|
|
return addr;
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// IPUxW
|
|
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 = [
|
|
// I00x0
|
|
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;
|
|
},
|
|
|
|
// I00xW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// I0Ux0
|
|
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;
|
|
},
|
|
// I0UxW
|
|
null,
|
|
|
|
null,
|
|
null,
|
|
|
|
// IP0x0
|
|
function(rn, shiftOp, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
shiftOp();
|
|
return gprs[rn] - cpu.shifterOperand;
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// IP0xW
|
|
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,
|
|
|
|
// IPUx0
|
|
function(rn, shiftOp, condOp) {
|
|
var gprs = cpu.gprs;
|
|
var address = function() {
|
|
shiftOp();
|
|
return gprs[rn] + cpu.shifterOperand;
|
|
};
|
|
address.writesPC = false;
|
|
return address;
|
|
},
|
|
|
|
// IPUxW
|
|
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)) {
|
|
// Our data type is a double--we'll lose bits if we do it all at once!
|
|
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)) {
|
|
// Our data type is a double--we'll lose bits if we do it all at once!
|
|
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 x = instruction & 0x00020000;
|
|
//var s = instruction & 0x00040000;
|
|
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) |
|
|
//(x ? 0x0000FF00 : 0x00000000) | // Irrelevant on ARMv4T
|
|
//(s ? 0x00FF0000 : 0x00000000) | // Irrelevant on ARMv4T
|
|
(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)) {
|
|
// Our data type is a double--we'll lose bits if we do it all at once!
|
|
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)) {
|
|
// Our data type is a double--we'll lose bits if we do it all at once!
|
|
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));
|
|
};
|
|
};
|