📄 cputhumbcore.pas
字号:
// 4 in all other cases.
test := regs[(t shr 3) and 7];
if test shr 31 <> 0 then test := not test;
if test and $FFFFFF00 = 0 then
c := 1
else if test and $FFFF0000 = 0 then
c := 2
else if test and $FF000000 = 0 then
c := 3
else
c := 4;
Dec(quota, c*cycI);
// Do the actual multiply
test := regs[(t shr 3) and 7] * regs[t and 7];
regs[t and 7] := test;
// Test flags
negative := test shr 31 <> 0;
zero := test = 0;
end;
$E: begin
// bic Rd, Rs
test := regs[t and 7] and not regs[(t shr 3) and 7];
regs[t and 7] := test;
end;
$F: begin
// mvn Rd, Rs
test := not regs[(t shr 3) and 7];
regs[t and 7] := test;
end;
else
test := 0; // shaddup
end;
negative := test shr 31 <> 0;
zero := test = 0;
end;
$44: begin
// Format 5: Hi register add, [add Rd/Hd, Hs/Rs] (both low is undefined)
case (t shr 6) and 3 of
1: begin
operand1 := t and 7;
regs[operand1] := regs[operand1] + regs[(t shr 3) and 7 + 8];
end;
2: begin
operand1 := t and 7 + 8;
regs[operand1] := regs[operand1] + regs[(t shr 3) and 7];
if operand1 = 15 then FlushPipeThumb;
end;
3: begin
operand1 := t and 7 + 8;
regs[operand1] := regs[operand1] + regs[(t shr 3) and 7 + 8];
if operand1 = 15 then FlushPipeThumb;
end;
end;
end;
$45: begin
// Format 5: Hi register compare, [cmp Rd/Hd, Hs/Rs] (both low is undefined)
case (t shr 6) and 3 of
1: begin
operand1 := regs[t and 7];
operand2 := regs[(t shr 3) and 7 + 8];
end;
2: begin
operand1 := regs[t and 7 + 8];
operand2 := regs[(t shr 3) and 7];
end;
3: begin
operand1 := regs[t and 7 + 8];
operand2 := regs[(t shr 3) and 7 + 8];
end;
else
UndefinedState('Thumb format 5: H1 and H2 = 0');
operand1 := 0;
operand2 := 0;
end;
test := operand1 - operand2;
neg1 := operand1 shr 31 <> 0;
neg2 := operand2 shr 31 <> 0;
negative := test shr 31 <> 0;
carry := (neg1 and not neg2) or (neg1 and not negative) or (not neg2 and not negative);
overflow := (neg1 and not neg2 and not negative) or (not neg1 and neg2 and negative);
zero := test = 0;
end;
$46: begin
// Format 5: Hi register move, [mov Rd/Hd, Hs/Rs] (both low is undefined)
case (t shr 6) and 3 of
1: regs[t and 7] := regs[(t shr 3) and 7 + 8];
2: begin
Rd := t and 7 + 8;
regs[Rd] := regs[(t shr 3) and 7];
if Rd = 15 then begin
regs[R15] := regs[R15] and not 1;
FlushPipeThumb;
end;
end;
3: begin
Rd := t and 7 + 8;
regs[Rd] := regs[(t shr 3) and 7 + 8];
if Rd = 15 then begin
regs[R15] := regs[R15] and not 1;
FlushPipeThumb;
end;
end;
end;
end;
$47: begin
// Format 5: Branch and exchange, [bx Rs/Hs] (H1=1 is undefined)
case (t shr 6) and 3 of
0: Rd := (t shr 3) and 7;
1: Rd := (t shr 3) and 7 + 8;
else
Rd := 0;
end;
// Using R15 as an operand
thumbMode := regs[Rd] and 1 <> 0;
regs[R15] := regs[Rd] and not 1;
if thumbMode then FlushPipeThumb else FlushPipeARM;
end;
$48..$4F: begin
// Format 6: PC-relative load, [ldr Rd, [PC, #Imm]]
regs[c and 7] := memReadWord((regs[R15] and $FFFFFFFC) + (t and $FF) shl 2);
Dec(quota, cycI);
end;
$50..$51: begin
// Format 7: Store with register offset, [str Rd, [Rb, Ro]]
memWriteWord(regs[(t shr 3) and 7] + regs[(t shr 6) and 7], regs[t and 7]);
end;
$52..$53: begin
// Format 8: Store halfword, [strh Rd, [Rb, Ro]]
memWriteHalfWord(regs[(t shr 3) and 7] + regs[(t shr 6) and 7], regs[t and 7]);
end;
$54..$55: begin
// Format 7: Store byte with register offset, [strb Rd, [Rb, Ro]]
memWriteByte(regs[(t shr 3) and 7] + regs[(t shr 6) and 7], regs[t and 7]);
end;
$56..$57: begin
// Format 8: Load signed byte, [ldrsb Rd, [Rb, Ro]]
test := memReadByte(regs[(t shr 3) and 7] + regs[(t shr 6) and 7]);
if test shr 7 <> 0 then test := test or $FFFFFF00;
regs[t and 7] := test;
Dec(quota, cycI);
end;
$58..$59: begin
// Format 7: Load with register offset, [ldr Rd, [Rb, Ro]]
regs[t and 7] := memReadWord(regs[(t shr 3) and 7] + regs[(t shr 6) and 7]);
Dec(quota, cycI);
end;
$5A..$5B: begin
// Format 8: Load halfword, [ldrh Rd, [Rb, Ro]]
regs[t and 7] := memReadHalfWord(regs[(t shr 3) and 7] + regs[(t shr 6) and 7]);
Dec(quota, cycI);
end;
$5C..$5D: begin
// Format 7: Load byte with register offset, [ldrb Rd, [Rb, Ro]]
regs[t and 7] := memReadByte(regs[(t shr 3) and 7] + regs[(t shr 6) and 7]);
Dec(quota, cycI);
end;
$5E..$5F: begin
// Format 8: Load signed halfword, [ldrsh Rd, [Rb, Ro]]
test := memReadHalfWord(regs[(t shr 3) and 7] + regs[(t shr 6) and 7]);
if test shr 15 <> 0 then test := test or $FFFF0000;
regs[t and 7] := test;
Dec(quota, cycI);
end;
$60..$67: begin
// Format 9: Store with immediate offset, [str Rd, [Rb, #Imm]]
memWriteWord(regs[(t shr 3) and 7] + ((t shr 6) and $1F) shl 2, regs[t and 7]);
end;
$68..$6F: begin
// Format 9: Load with immediate offset, [ldr Rd, [Rb, #Imm]]
regs[t and 7] := memReadWord(regs[(t shr 3) and 7] + ((t shr 6) and $1F) shl 2);
Dec(quota, cycI);
end;
$70..$77: begin
// Format 9: Store byte with immediate offset, [strb Rd, [Rb, #Imm]]
memWriteByte(regs[(t shr 3) and 7] + ((t shr 6) and $1F), regs[t and 7]);
end;
$78..$7F: begin
// Format 9: Load byte with immediate offset, [ldrb Rd, [Rb, #Imm]]
regs[t and 7] := memReadByte(regs[(t shr 3) and 7] + ((t shr 6) and $1F));
Dec(quota, cycI);
end;
$80..$87: begin
// Format 10: Store halfword, [strh Rd, [Rb, #Imm]]
memWriteHalfWord(regs[(t shr 3) and 7] + ((t shr 6) and $1F) shl 1, regs[t and 7]);
end;
$88..$8F: begin
// Format 10: Load halfword, [ldrh Rd, [Rb, #Imm]]
regs[t and 7] := memReadHalfWord(regs[(t shr 3) and 7] + ((t shr 6) and $1F) shl 1);
Dec(quota, cycI);
end;
$90..$97: begin
// Format 11: SP-relative store, [str Rd, [SP, #Imm]]
memWriteWord(regs[R13] + (t and $FF) shl 2, regs[c and 7]);
end;
$98..$9F: begin
// Format 11: SP-relative load, [ldr Rd, [SP, #Imm]]
regs[c and 7] := memReadWord(regs[R13] + (t and $FF) shl 2);
Dec(quota, cycI);
end;
$A0..$A7: begin
// Format 12: Load address, [add Rd, PC, #Imm]
regs[c and 7] := (regs[R15] and $FFFFFFFC) + (t and $FF) shl 2;
end;
$A8..$AF: begin
// Format 12: Load address, [add Rd, SP, #Imm]
regs[c and 7] := regs[R13] + (t and $FF) shl 2;
end;
$B0: begin
// Format 13: Add offset to stack pointer [add SP, #+/-Imm]
test := (t and $7F) shl 2;
if t and (1 shl 7) <> 0 then Dec(regs[R13], test) else Inc(regs[R13], test);
end;
$B1..$B3, $B6..$BB, $BE..$BF, $E8..$EF: begin
// Undefined Opcode
UndefinedOpcode;
end;
$B4: begin
// Format 14: push {rlist}
for i := 7 downto 0 do
if t and (1 shl i) <> 0 then begin
Dec(regs[R13], 4);
memWriteWord(regs[R13], regs[i]);
end;
end;
$B5: begin
// Format 14: push {rlist,LR}
Dec(regs[R13], 4);
memWriteWord(regs[R13], regs[R14]);
for i := 7 downto 0 do
if t and (1 shl i) <> 0 then begin
Dec(regs[R13], 4);
memWriteWord(regs[R13], regs[i]);
end;
end;
$BC: begin
// Format 14: pop {rlist}
for i := 0 to 7 do
if t and (1 shl i) <> 0 then begin
regs[i] := memReadWord(regs[R13]);
Inc(regs[R13], 4);
end;
Dec(quota, cycI);
end;
$BD: begin
// Format 14: pop {rlist, PC}
for i := 0 to 7 do
if t and (1 shl i) <> 0 then begin
regs[i] := memReadWord(regs[R13]);
Inc(regs[R13], 4);
end;
regs[R15] := memReadWord(regs[R13]);
Inc(regs[R13], 4);
FlushPipeThumb;
Dec(quota, cycI);
end;
$C0..$C7: begin
// Format 15: stmia Rb!, {rlist}
for i := 0 to 7 do
if t and (1 shl i) <> 0 then begin
memWriteWord(regs[c and 7], regs[i]);
Inc(regs[c and 7], 4);
end;
end;
$C8..$CF: begin
// Format 15: ldmia Rb!, {rlist}
for i := 0 to 7 do
if t and (1 shl i) <> 0 then begin
regs[i] := memReadWord(regs[c and 7]);
Inc(regs[c and 7], 4);
end;
Dec(quota, cycI);
end;
$D0..$DE: begin
// Format 16: Conditionial branch, [bXX label]
rs := c and $F;
{$I incTestCond.pas}
if cond then begin
test := t and $FF;
if test shr 7 <> 0 then test := test or $FFFFFF00;
Inc(regs[R15], test shl 1);
FlushPipeThumb;
end;
end;
$DF: begin
// Format 17: Software Interrupt, [swi value8]
cpuCurrentOpcode := t;
SoftwareInterrupt;
end;
$E0..$E7: begin
// Format 18: Unconditional branch, [b label]
test := t and $7FF;
if test shr 10 <> 0 then test := test or $FFFFF800;
Inc(regs[R15], test shl 1);
FlushPipeThumb;
end;
$F0..$F7: begin
// Format 19: Long branch with link (hw1), [part one of bl label]
test := t and $7FF;
if test shr 10 <> 0 then test := test or $FFFFF800;
regs[R14] := regs[R15] + test shl 12;
end;
$F8..$FF: begin
// Format 19: Long branch with link (hw2), [part two of bl label]
test := t and $7FF;
operand1 := regs[R15] - 2;
regs[R15] := regs[R14] + test shl 1;
regs[R14] := operand1 or 1;
FlushPipeThumb;
end;
end;
// Check for a breakpoint
if memStopAtAddy(regs[R15] - 2) then begin
hitBreakpoint := true;
Exit;
end;
until (quota <= 0) or not thumbMode;
// Check for a breakpoint on the next opcode
if (not thumbMode) and not haveFlippedThumb then
hitBreakpoint := memStopAtAddy(regs[R15] - 4);
end;
//////////////////////////////////////////////////////////////////////
end.
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -