mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
273 lines
7 KiB
Text
273 lines
7 KiB
Text
#---------------------------------------------------------------------
|
|
# 8.3.8 INSTRUCTION FLOW
|
|
#---------------------------------------------------------------------
|
|
|
|
#---------------------------------------------------------------------
|
|
# ACALL - Application Call
|
|
# I. disp -> {0, 4, ..., 1020}
|
|
#---------------------------------------------------------------------
|
|
|
|
# ACALL Format I:
|
|
# Operation: LR <- PC + 2
|
|
# Syntax: acall disp
|
|
# 1101 nnnn nnnn 0000
|
|
|
|
ACALLdisp: disp is disp4_8 [ disp = ACBA + (disp4_8 << 2); ] { export *:4 disp; }
|
|
|
|
:ACALL ACALLdisp is op12_4=0xd & op0_4=0 & ACALLdisp
|
|
{
|
|
LR = inst_next;
|
|
call ACALLdisp;
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
# RET{cond4} - Conditional Return from Subroutine
|
|
# I. cond4 -> {eq, ne, cc/hs, cs/lo, ge, lt, mi, pl, ls, gt, le, hi, vs, vc, qs, al}
|
|
# s -> {0, 1, ..., 15}
|
|
#---------------------------------------------------------------------
|
|
|
|
retCond4Sub: rs0 is rs0 & rs0=0xf { R12 = 0x1;} #PC (0xf)
|
|
retCond4Sub: rs0 is rs0 & rs0=0xe { R12 = -0x1;} #LR (0xe)
|
|
retCond4Sub: rs0 is rs0 & rs0=0xd { R12 = 0x0;} #SP (0xd)
|
|
retCond4Sub: rs0 is rs0 & rs0=0xc {} #Else R12 is R12
|
|
retCond4Sub: rs0 is rs0 {R12 = rs0;} #Else
|
|
|
|
|
|
#RET{Cond4} Format I:
|
|
#Operation:
|
|
# Conditional return from subroutine with move and test of return value:
|
|
# if (Rs != {LR, SP, PC})
|
|
# R12 <- Rs
|
|
# PC <- LR
|
|
# Conditional return from subroutine with return of false value:
|
|
# else if (Rs == LR)
|
|
# R12 <- -1
|
|
# PC <- LR
|
|
# Conditional return from subroutine with return of false value:
|
|
# else if (Rs == SP)
|
|
# R12 <- 0
|
|
# PC <- LR
|
|
# Conditional return from subroutine with return of true value:
|
|
# else if (Rs == PC)
|
|
# R12 <- 1
|
|
# PC <- LR
|
|
#Syntax: ret{cond4} Rs
|
|
#010 1111 0 CCCC ssss
|
|
#0101 1110 CCCC ssss
|
|
:RET^{COND_4_4} retCond4Sub is op13_3=0x2 & op9_4=0xf & op8_1 = 0x0 & COND_4_4 & retCond4Sub {
|
|
# Test Condition
|
|
build COND_4_4;
|
|
build retCond4Sub;
|
|
# Flags Set:
|
|
V = 0x0;
|
|
C = 0x0;
|
|
NZSTATUS(R12);
|
|
# End Operation:
|
|
#PC = LR;
|
|
return [ LR ];
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
# BR{cond} - Branch if Condition Satisfied
|
|
# I. cond3 -> {eq, ne, cc/hs, cs/lo, ge, lt, mi, pl}
|
|
# disp -> {-256, -254, ..., 254}
|
|
# II. cond4 -> {eq, ne, cc/hs, cs/lo, ge, lt, mi, pl, ls, gt, le, hi, vs, vc, qs, al}
|
|
# disp -> {-2097152, -2097150, ..., 2097150}
|
|
#---------------------------------------------------------------------
|
|
|
|
sDisp8: sdisp is sdisp4_8
|
|
[ sdisp = inst_start + (sdisp4_8 << 1); ]
|
|
{
|
|
export *:4 sdisp;
|
|
}
|
|
|
|
sDisp21: sdisp21 is disp21part2_4_1 & disp21part3_9_4; disp21part1_0_16
|
|
[ sdisp21 = inst_start + (((disp21part3_9_4 << 17) | (disp21part2_4_1 << 16) | disp21part1_0_16) << 1); ]
|
|
{
|
|
export *:4 sdisp21;
|
|
}
|
|
|
|
#BR{cond3} Format I:
|
|
#Operation:
|
|
# Branch if condition satisfied:
|
|
# if(cond3)
|
|
# PC <- PC + (SE(disp8)<<1)
|
|
# else
|
|
# PC <- PC + 2;
|
|
#Syntax: br{cond3}disp
|
|
#110 0 nnnnnnnn 0 CCC
|
|
#1100 nnnn nnnn 0CCC
|
|
|
|
|
|
:BR^{COND_3} sDisp8 is op13_3=0x6 & op12_1=0x0 & op3_1 = 0x0 & COND_3 & sDisp8
|
|
{
|
|
tst:1 = COND_3;
|
|
if (tst) goto sDisp8;
|
|
}
|
|
|
|
#BR{cond4} Format II:
|
|
#Operation:
|
|
# Branch if condition satisfied:
|
|
# if(cond4)
|
|
# PC <- PC + (SE(disp21)<<1)
|
|
# else
|
|
# PC <- PC + 4;
|
|
#Syntax: br{cond3}disp
|
|
#111 nnnn 0100 n CCCC nnnnnnnnnnnnnnnn
|
|
#111n nnn0 100n CCCC nnnn nnnn nnnn nnnn
|
|
:BR^{COND_4_0} sDisp21 is (op13_3=0x7 & op5_4=0x4 & COND_4_0) ... & sDisp21
|
|
{
|
|
build COND_4_0;
|
|
goto sDisp21;
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
# RJMP - Relative Jump
|
|
# I. disp -> {-1024, -1022, ..., 1022}
|
|
#---------------------------------------------------------------------
|
|
|
|
# RJMP Format I:
|
|
# Operation: PC <- PC + (SE(disp10)<<1);
|
|
# Syntax: rjmp PC[disp]
|
|
# 1100 nnnn nnnn 10nn
|
|
|
|
RJMPdisp: disp is disp4_8 & sdisp0_2
|
|
[ disp = inst_start + (((sdisp0_2 << 8) | disp4_8) << 1); ]
|
|
{
|
|
export *:4 disp;
|
|
}
|
|
|
|
:RJMP RJMPdisp is op12_4=0xc & op2_2=0x2 & RJMPdisp
|
|
{
|
|
goto RJMPdisp;
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
# ICALL - Subroutine Call
|
|
# I. d -> {0, 1, ..., 15}
|
|
#---------------------------------------------------------------------
|
|
|
|
# ICALL Format I:
|
|
# Operation: LR <- PC + 2
|
|
# PC <- Rd
|
|
# Syntax: icall Rd
|
|
# 0101 1101 0001 dddd
|
|
|
|
:ICALL rd0 is op4_12=0x5d1 & rd0 {
|
|
tmp:4 = rd0;
|
|
LR = inst_next;
|
|
call [tmp];
|
|
}
|
|
|
|
#---------------------------------------------------------------------
|
|
# MCALL - Subroutine Call
|
|
# I. p -> {0, 1, ..., 15}
|
|
# disp -> {-131072, -131068, ..., 131068}
|
|
#---------------------------------------------------------------------
|
|
|
|
RP0Disp16: rp0^"["^disp^"]" is rp0; disp_16
|
|
[ disp = (disp_16 << 2); ]
|
|
{
|
|
val:4 = (rp0 & 0xfffffffc) + disp;
|
|
export *:4 val;
|
|
}
|
|
|
|
RP0Disp16_2: PC[disp] is disp_16 & PC
|
|
[ disp = (inst_start & 0xfffffffc) + (disp_16 << 2); ]
|
|
{
|
|
export *:4 disp;
|
|
}
|
|
|
|
# MCALL Format I:
|
|
# Operation: LR <- PC + 4
|
|
# PC <- *((Rp & 0xfffffffc) + (SE(disp16) << 2))
|
|
# Syntax: mcall Rp[disp]
|
|
# 1111 0000 0001 pppp nnnn nnnn nnnn nnnn
|
|
|
|
IndirectPlaceHolder: " " is epsilon{}
|
|
|
|
:MCALL RP0Disp16 is op4_12=0xf01 ... & RP0Disp16 {
|
|
LR = inst_next;
|
|
PC = RP0Disp16;
|
|
call [PC];
|
|
}
|
|
|
|
:MCALL RP0Disp16_2^IndirectPlaceHolder is op4_12=0xf01 & rp0=0xf ; RP0Disp16_2 & IndirectPlaceHolder {
|
|
LR = inst_next;
|
|
PC = RP0Disp16_2;
|
|
call [PC];
|
|
}
|
|
|
|
RelDisp10: val is disp4_8 & disp0_2 [ctx_rel0_8=disp4_8; ctx_rel8_2=disp0_2; val= inst_start + (ctx_rel10 << 1); ] {
|
|
export *:4 val;
|
|
}
|
|
|
|
RelDisp21: val is imm16 [ctx_rel0_16=imm16; val=inst_start + (ctx_rel21 << 1); ] {
|
|
export *:4 val;
|
|
}
|
|
|
|
:RCALL PC[RelDisp10] is op13_3=6 & op12_1=0 & b02=1 & b03=1 & PC & RelDisp10 {
|
|
LR = inst_next;
|
|
call RelDisp10;
|
|
}
|
|
|
|
:RCALL PC[RelDisp21] is op13_3=7 & op5_4=5 & op0_4=0 & PC & b04 & bp9_4; RelDisp21 [ctx_rel16_1=b04; ctx_rel17_4=bp9_4;] {
|
|
LR = inst_next;
|
|
call RelDisp21;
|
|
}
|
|
|
|
# The RETx instructions are somewhat complicated. The architecutre version (A/B)
|
|
# determines hardware actions as well as the status of the mode bits M2:M0. For now,
|
|
# we follow the "B" model as it's simpler and have a custom pcode. For RETE I also
|
|
# picked a given interrupt level that would actually be determined by the mode bits.
|
|
:RETD is op0_16=0xd623 {
|
|
SR = RSR_DBG;
|
|
SRTOFLAGS();
|
|
return [ RAR_DBG ];
|
|
}
|
|
|
|
:RETE is op0_16=0xd603 {
|
|
CheckAndRestoreInterupt();
|
|
SR = RSR_INT0;
|
|
SRTOFLAGS();
|
|
L = 0;
|
|
LTOSR();
|
|
return [ RAR_INT0 ];
|
|
}
|
|
|
|
:RETS is op0_16=0xd613 {
|
|
CheckAndRestoreSupervisor();
|
|
SR = RSR_SUP;
|
|
SRTOFLAGS();
|
|
return [ RAR_SUP ];
|
|
}
|
|
|
|
:RETJ is op0_16=0xd633 {
|
|
JavaTrap();
|
|
J = 1;
|
|
R = 0;
|
|
JRGMTOSR();
|
|
return [ LR ];
|
|
}
|
|
|
|
:SCALL is op0_16=0xd733 {
|
|
SupervisorCallSetup();
|
|
LR = inst_next;
|
|
tmp:4 = EVBA + 0x100;
|
|
call [ tmp ];
|
|
}
|
|
|
|
JV3: val is b06=1 & ctx_rel3 [ val = ctx_rel3 << 0; ] { export *[const]:1 val; }
|
|
JV3: val is b06=0 & disp4_3 [ val = disp4_3+1; ] { export *[const]:1 val; }
|
|
:INCJOSP JV3 is op7_9=0x1ad & op0_4=0x3 & disp4_3 & JV3 [ctx_rel3 = disp4_3;] {
|
|
JavaCheckStack(JOSP,JV3);
|
|
JOSP = JOSP + sext(JV3);
|
|
}
|
|
|
|
:POPJC is op0_16=0xd713 {
|
|
JavaPopContext();
|
|
}
|
|
|
|
:PUSHJC is op0_16=0xd723 {
|
|
JavaPushContext();
|
|
}
|