ghidra/Ghidra/Processors/Atmel/data/languages/avr32a_instruction_flow.sinc
2025-09-11 13:21:58 +00:00

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();
}