arm32: fixed VCVT, VLDR/VSTR
This commit is contained in:
parent
098dcda93a
commit
d733a2cd27
|
@ -1811,15 +1811,6 @@ ARMCoreArm.prototype.constructVFP3Register = function(condOp, opcode, nOperandRe
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if opc2 != '000' && !(opc2 IN "10x") then SEE "Related encodings";
|
|
||||||
to_integer = (opc2<2> == '1'); dp_operation = (sz == 1);
|
|
||||||
if to_integer then
|
|
||||||
unsigned = (opc2<0> == '0'); round_zero = (op == '1');
|
|
||||||
d = UInt(Vd:D); m = if dp_operation then UInt(M:Vm) else UInt(Vm:M);
|
|
||||||
else
|
|
||||||
unsigned = (op == '0'); round_nearest = FALSE; // FALSE selects FPSCR rounding
|
|
||||||
m = UInt(Vm:M); d = if dp_operation then UInt(D:Vd) else UInt(Vd:D);
|
|
||||||
|
|
||||||
if ConditionPassed() then
|
if ConditionPassed() then
|
||||||
EncodingSpecificOperations(); CheckVFPEnabled(TRUE);
|
EncodingSpecificOperations(); CheckVFPEnabled(TRUE);
|
||||||
if to_integer then
|
if to_integer then
|
||||||
|
@ -1833,24 +1824,11 @@ if ConditionPassed() then
|
||||||
else
|
else
|
||||||
S[d] = FixedToFP(S[m], 32, 0, unsigned, round_nearest, TRUE);
|
S[d] = FixedToFP(S[m], 32, 0, unsigned, round_nearest, TRUE);
|
||||||
*/
|
*/
|
||||||
ARMCoreArm.prototype.constructVCVT = function(condOp, D, opc2, Vd, sz, op, M, Vm) {
|
ARMCoreArm.prototype.constructVCVT = function(condOp, d, m, to_integer, dp_operation, unsigned, round_zero, round_nearest) {
|
||||||
var cpu : ARMCoreType = this.cpu;
|
var cpu : ARMCoreType = this.cpu;
|
||||||
var sregs = cpu.sfprs;
|
var sregs = cpu.sfprs;
|
||||||
var dregs = cpu.dfprs;
|
var dregs = cpu.dfprs;
|
||||||
var iregs = cpu.ifprs;
|
var iregs = cpu.ifprs;
|
||||||
var to_integer = (opc2 & 0x4) != 0;
|
|
||||||
var dp_operation = (sz & 1) != 0;
|
|
||||||
var unsigned = (opc2 & 0x1) == 0;
|
|
||||||
var round_zero = false;
|
|
||||||
var round_nearest = false;
|
|
||||||
if (to_integer) {
|
|
||||||
unsigned = (opc2 & 0x1) == 0;
|
|
||||||
round_zero = (op & 0x1) != 0;
|
|
||||||
} else {
|
|
||||||
unsigned = (op & 0x1) == 0;
|
|
||||||
round_nearest = false;
|
|
||||||
}
|
|
||||||
//console.log("VCVT: " + hex(D) + " " + hex(opc2) + " " + hex(Vd) + " " + hex(sz) + " " + hex(op) + " " + hex(M) + " " + hex(Vm) + " " + to_integer + " " + unsigned);
|
|
||||||
return function() {
|
return function() {
|
||||||
cpu.mmu.waitPrefetch32(cpu.gprs[ARMRegs.PC]);
|
cpu.mmu.waitPrefetch32(cpu.gprs[ARMRegs.PC]);
|
||||||
if (condOp && !condOp()) {
|
if (condOp && !condOp()) {
|
||||||
|
@ -1860,11 +1838,11 @@ ARMCoreArm.prototype.constructVCVT = function(condOp, D, opc2, Vd, sz, op, M, Vm
|
||||||
var dest : number;
|
var dest : number;
|
||||||
// get source
|
// get source
|
||||||
if (to_integer && dp_operation) {
|
if (to_integer && dp_operation) {
|
||||||
src = dregs[M];
|
src = dregs[m];
|
||||||
} else if (to_integer) {
|
} else if (to_integer) {
|
||||||
src = sregs[M];
|
src = sregs[m];
|
||||||
} else {
|
} else {
|
||||||
src = iregs[M];
|
src = iregs[m];
|
||||||
}
|
}
|
||||||
// convert
|
// convert
|
||||||
if (to_integer) {
|
if (to_integer) {
|
||||||
|
@ -1874,11 +1852,11 @@ ARMCoreArm.prototype.constructVCVT = function(condOp, D, opc2, Vd, sz, op, M, Vm
|
||||||
}
|
}
|
||||||
// store result
|
// store result
|
||||||
if (to_integer) {
|
if (to_integer) {
|
||||||
iregs[D] = dest;
|
iregs[d] = dest;
|
||||||
} else if (dp_operation) {
|
} else if (dp_operation) {
|
||||||
dregs[D] = dest;
|
dregs[d] = dest;
|
||||||
} else {
|
} else {
|
||||||
sregs[D] = dest;
|
sregs[d] = dest;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1935,8 +1913,8 @@ ARMCoreArm.prototype.constructVSTR = function(condOp, srcReg, address, single_re
|
||||||
if (single_reg) {
|
if (single_reg) {
|
||||||
cpu.mmu.store32(addr, iregs[srcReg]);
|
cpu.mmu.store32(addr, iregs[srcReg]);
|
||||||
} else {
|
} else {
|
||||||
cpu.mmu.store32(addr, iregs[srcReg*2]);
|
cpu.mmu.store32(addr, iregs[srcReg]);
|
||||||
cpu.mmu.store32(addr+4, iregs[srcReg*2+1]);
|
cpu.mmu.store32(addr+4, iregs[srcReg+1]);
|
||||||
}
|
}
|
||||||
cpu.mmu.wait32(addr);
|
cpu.mmu.wait32(addr);
|
||||||
cpu.mmu.wait32(cpu.gprs[ARMRegs.PC]);
|
cpu.mmu.wait32(cpu.gprs[ARMRegs.PC]);
|
||||||
|
@ -2015,17 +1993,40 @@ ARMCoreArm.prototype.constructVCMP = function(condOp, d, Vd, sz, E, m, Vm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMCoreArm.prototype.constructVMOV = function(condOp, to_arm_reg, n, t) {
|
ARMCoreArm.prototype.constructVCMP0 = function(condOp, d, Vd, sz, E) {
|
||||||
var cpu : ARMCoreType = this.cpu;
|
var cpu : ARMCoreType = this.cpu;
|
||||||
var srcregs = to_arm_reg ? cpu.ifprs : cpu.gprs;
|
var sregs = cpu.sfprs;
|
||||||
var destregs = to_arm_reg ? cpu.gprs : cpu.ifprs;
|
var dregs = cpu.dfprs;
|
||||||
//console.log('VMOV: ' + hex(to_arm_reg) + ' ' + hex(n) + ' ' + hex(t));
|
|
||||||
return function() {
|
return function() {
|
||||||
cpu.mmu.waitPrefetch32(cpu.gprs[ARMRegs.PC]);
|
cpu.mmu.waitPrefetch32(cpu.gprs[ARMRegs.PC]);
|
||||||
if (condOp && !condOp()) {
|
if (condOp && !condOp()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
destregs[t] = srcregs[n];
|
let op1, op2=0;
|
||||||
|
if (sz) {
|
||||||
|
op1 = dregs[d];
|
||||||
|
} else {
|
||||||
|
op1 = sregs[d];
|
||||||
|
}
|
||||||
|
let result = FPCompare(op1, op2);
|
||||||
|
cpu.cpsrN = (result & 8) != 0;
|
||||||
|
cpu.cpsrZ = (result & 4) != 0;
|
||||||
|
cpu.cpsrC = (result & 2) != 0;
|
||||||
|
cpu.cpsrV = (result & 1) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ARMCoreArm.prototype.constructVMOV = function(condOp, to_arm_reg, n, t) {
|
||||||
|
var cpu : ARMCoreType = this.cpu;
|
||||||
|
return function() {
|
||||||
|
cpu.mmu.waitPrefetch32(cpu.gprs[ARMRegs.PC]);
|
||||||
|
if (condOp && !condOp()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (to_arm_reg) {
|
||||||
|
cpu.gprs[t] = cpu.ifprs[n];
|
||||||
|
} else {
|
||||||
|
cpu.ifprs[n] = cpu.gprs[t];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3976,6 +3977,7 @@ ARMCore.prototype.compileArm = function(instruction) {
|
||||||
op = this.armCompiler.constructVPOP(condOp, ((user?16:0)|crd)*2, immediate, false);
|
op = this.armCompiler.constructVPOP(condOp, ((user?16:0)|crd)*2, immediate, false);
|
||||||
}
|
}
|
||||||
// VLDR, VSTR
|
// VLDR, VSTR
|
||||||
|
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VSTR?lang=en
|
||||||
else if ((instruction & 0x0f200f00) == 0x0d000a00) {
|
else if ((instruction & 0x0f200f00) == 0x0d000a00) {
|
||||||
immediate *= 4;
|
immediate *= 4;
|
||||||
if (!u) immediate = -immediate;
|
if (!u) immediate = -immediate;
|
||||||
|
@ -4022,16 +4024,34 @@ ARMCore.prototype.compileArm = function(instruction) {
|
||||||
}
|
}
|
||||||
// VCVT, VCVTR, VCVT
|
// VCVT, VCVTR, VCVT
|
||||||
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VCVT--VCVTR--between-floating-point-and-integer--Floating-point-
|
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VCVT--VCVTR--between-floating-point-and-integer--Floating-point-
|
||||||
|
/*
|
||||||
|
if opc2 != '000' && !(opc2 IN "10x") then SEE "Related encodings";
|
||||||
|
to_integer = (opc2<2> == '1'); dp_operation = (sz == 1);
|
||||||
|
if to_integer then
|
||||||
|
unsigned = (opc2<0> == '0'); round_zero = (op == '1');
|
||||||
|
d = UInt(Vd:D); m = if dp_operation then UInt(M:Vm) else UInt(Vm:M);
|
||||||
|
else
|
||||||
|
unsigned = (op == '0'); round_nearest = FALSE; // FALSE selects FPSCR rounding
|
||||||
|
m = UInt(Vm:M); d = if dp_operation then UInt(D:Vd) else UInt(Vd:D);
|
||||||
|
*/
|
||||||
else if ((instruction & 0x0FB80E50) == 0x0EB80A40) {
|
else if ((instruction & 0x0FB80E50) == 0x0EB80A40) {
|
||||||
const cond = (instruction >> 28) & 0xf;
|
const cond = (instruction >> 28) & 0xf;
|
||||||
const D = (instruction >> 22) & 0x1;
|
const D = (instruction >> 22) & 0x1;
|
||||||
const opc2 = (instruction >> 16) & 0x7;
|
const opc2 = (instruction >> 16) & 0x7;
|
||||||
const Vd = (instruction >> 12) & 0xf;
|
const Vd = (instruction >> 12) & 0xf;
|
||||||
const sz = (instruction >> 8) & 0x1;
|
const sz = (instruction >> 8) & 0x1;
|
||||||
const to_fixed = (instruction >> 7) & 0x1;
|
const op0 = (instruction >> 7) & 0x1;
|
||||||
const M = (instruction >> 5) & 0x1;
|
const M = (instruction >> 5) & 0x1;
|
||||||
const Vm = instruction & 0xf;
|
const Vm = instruction & 0xf;
|
||||||
op = this.armCompiler.constructVCVT(condOp, D, opc2, Vd, sz, to_fixed, M, Vm);
|
const to_integer = opc2 & 0x4;
|
||||||
|
const dp_operation = sz != 0;
|
||||||
|
const unsigned = to_integer ? opc2 & 0x1 : 0;
|
||||||
|
const round_zero = op0 != 0;
|
||||||
|
const round_nearest = false;
|
||||||
|
const d = sz ? (D?16:0)|Vd : (Vd<<1)|(D?1:0);
|
||||||
|
const m = sz ? (M?16:0)|Vm : (Vm<<1)|(M?1:0);
|
||||||
|
//console.log("VCVT", d, m, opc2, to_integer, dp_operation, unsigned, round_zero, round_nearest);
|
||||||
|
op = this.armCompiler.constructVCVT(condOp, d, m, to_integer, dp_operation, unsigned, round_zero, round_nearest);
|
||||||
op.writesPC = false;
|
op.writesPC = false;
|
||||||
}
|
}
|
||||||
// VCVT f64/f32
|
// VCVT f64/f32
|
||||||
|
@ -4106,11 +4126,27 @@ ARMCore.prototype.compileArm = function(instruction) {
|
||||||
op = this.armCompiler.constructVCMP(condOp, d, Vd, sz, E, m, Vm);
|
op = this.armCompiler.constructVCMP(condOp, d, Vd, sz, E, m, Vm);
|
||||||
op.writesPC = false;
|
op.writesPC = false;
|
||||||
}
|
}
|
||||||
|
// VCMP #0
|
||||||
|
else if ((instruction & 0x0FBF0EFF) == 0x0EB50A40) {
|
||||||
|
const cond = (instruction >> 28) & 0xf;
|
||||||
|
const D = (instruction >> 22) & 0x1;
|
||||||
|
const Vd = (instruction >> 12) & 0xf;
|
||||||
|
const sz = (instruction >> 8) & 0x1;
|
||||||
|
const E = (instruction >> 7) & 0x1;
|
||||||
|
const M = (instruction >> 5) & 0x1;
|
||||||
|
const Vm = instruction & 0x0000000F;
|
||||||
|
const d = sz ? (D?16:0)|Vd : (Vd<<1)|(D?1:0);
|
||||||
|
const m = sz ? (M?16:0)|Vm : (Vm<<1)|(M?1:0);
|
||||||
|
|
||||||
|
var condOp = this.conds[cond];
|
||||||
|
op = this.armCompiler.constructVCMP0(condOp, d, Vd, sz, E, m, Vm);
|
||||||
|
op.writesPC = false;
|
||||||
|
}
|
||||||
// vmrs apsr_nzcv, fpscr (ignore, we always call this after CMP)
|
// vmrs apsr_nzcv, fpscr (ignore, we always call this after CMP)
|
||||||
else if (instruction == 0xeef1fa10) {
|
else if (instruction == 0xeef1fa10) {
|
||||||
op = this.armCompiler.constructNOP();
|
op = this.armCompiler.constructNOP();
|
||||||
}
|
}
|
||||||
// VMOV
|
// VMOV - https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VMOV--between-ARM-core-register-and-single-precision-register-
|
||||||
else if ((instruction & 0x0FE00F10) == 0x0E000A10) {
|
else if ((instruction & 0x0FE00F10) == 0x0E000A10) {
|
||||||
const cond = (instruction >> 28) & 0xf;
|
const cond = (instruction >> 28) & 0xf;
|
||||||
const opc1 = (instruction >> 20) & 0x1;
|
const opc1 = (instruction >> 20) & 0x1;
|
||||||
|
@ -4118,6 +4154,7 @@ ARMCore.prototype.compileArm = function(instruction) {
|
||||||
const Rt = (instruction >> 12) & 0xf;
|
const Rt = (instruction >> 12) & 0xf;
|
||||||
const N = (instruction >> 7) & 0x1;
|
const N = (instruction >> 7) & 0x1;
|
||||||
var condOp = this.conds[cond];
|
var condOp = this.conds[cond];
|
||||||
|
//console.log("VMOV", instruction.toString(16), opc1, Vn, Rt, N);
|
||||||
op = this.armCompiler.constructVMOV(condOp, opc1, (Vn<<1)|(N?1:0), Rt);
|
op = this.armCompiler.constructVMOV(condOp, opc1, (Vn<<1)|(N?1:0), Rt);
|
||||||
}
|
}
|
||||||
// vmov.32 dn[i], rn
|
// vmov.32 dn[i], rn
|
||||||
|
|
|
@ -96,6 +96,7 @@ export class ARM32Machine extends BasicScanlineMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
this.ram.fill(0);
|
||||||
if (this.rom) {
|
if (this.rom) {
|
||||||
this.ram.set(this.rom, this.rombase);
|
this.ram.set(this.rom, this.rombase);
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue