304 lines
12 KiB
Plaintext
304 lines
12 KiB
Plaintext
# Specification for the ARM Version 4, 4T, 5, 5T, 5E
|
|
# The following boolean defines control specific support: T_VARIANT, VERSION_5, VERSION_5E
|
|
|
|
define endian=$(ENDIAN);
|
|
define alignment=2;
|
|
|
|
define space ram type=ram_space size=4 default;
|
|
define space register type=register_space size=4;
|
|
|
|
define register offset=0x0020 size=4 [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];
|
|
define register offset=0x0060 size=1 [ NG ZR CY OV tmpNG tmpZR tmpCY tmpOV shift_carry TB Q GE1 GE2 GE3 GE4 ];
|
|
define register offset=0x0070 size=4 [ cpsr spsr ];
|
|
define register offset=0x0080 size=4 [ mult_addr ]; # Special internal register for dealing with multiple stores/loads
|
|
define register offset=0x0084 size=4 [ r14_svc r13_svc spsr_svc ];
|
|
define register offset=0x0090 size=8 [ mult_dat8 ]; # Special internal register for dealing with multiple stores/loads
|
|
define register offset=0x0090 size=16 [ mult_dat16 ]; # Special internal register for dealing with multiple stores/loads
|
|
define register offset=0x00A0 size=4 [ fpsr ]; # floating point state register (for FPA10 floating-point accelerator)
|
|
define register offset=0x00B0 size=1 [ ISAModeSwitch ]; # generic name for TB ThumbBit - set same as TB
|
|
|
|
@define FPSCR_N "fpscr[31,1]"
|
|
@define FPSCR_Z "fpscr[30,1]"
|
|
@define FPSCR_C "fpscr[29,1]"
|
|
@define FPSCR_V "fpscr[28,1]"
|
|
|
|
@if defined(VFPv2) || defined(VFPv3) || defined(SIMD)
|
|
define register offset=0x00B0 size=4 [ fpsid fpscr fpexc mvfr0 mvfr1 ];
|
|
@endif
|
|
define register offset=0x0100 size=10 [ fp0 fp1 fp2 fp3 fp4 fp5 fp6 fp7 ]; # eight 80-bit floating registers
|
|
|
|
# pseudo-registers for coprocessor calculations
|
|
define register offset=0x0200 size=4 [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ];
|
|
|
|
# Advanced SIMD and VFP extension registers
|
|
@if defined(VFPv2) || defined(VFPv3)
|
|
|
|
@if ENDIAN == "little"
|
|
define register offset=0x0300 size=4 [ s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15
|
|
s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 ];
|
|
@else # ENDIAN == "big"
|
|
define register offset=0x0300 size=4 [ s31 s30 s29 s28 s27 s26 s25 s24 s23 s22 s21 s20 s19 s18 s17 s16
|
|
s15 s14 s13 s12 s11 s10 s9 s8 s7 s6 s5 s4 s3 s2 s1 s0 ];
|
|
@endif # ENDIAN = "big"
|
|
|
|
@endif # VFPv2 || VFPv3
|
|
|
|
@if defined(VFPv2)
|
|
|
|
@if ENDIAN == "little"
|
|
define register offset=0x0300 size=8 [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ];
|
|
@else # ENDIAN == "big"
|
|
define register offset=0x0300 size=8 [ d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ];
|
|
@endif # ENDIAN = "big"
|
|
|
|
@endif # VFPv2
|
|
|
|
@if defined(SIMD) || defined(VFPv3)
|
|
|
|
@if ENDIAN == "little"
|
|
define register offset=0x0300 size=8 [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15
|
|
d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 ];
|
|
@else # ENDIAN == "big"
|
|
define register offset=0x0300 size=8 [ d31 d30 d29 d28 d27 d26 d25 d24 d23 d22 d21 d20 d19 d18 d17 d16
|
|
d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ];
|
|
@endif # ENDIAN = "big"
|
|
|
|
@endif # SIMD || VFPv3
|
|
|
|
@if defined(SIMD)
|
|
|
|
@if ENDIAN == "little"
|
|
define register offset=0x0300 size=16 [ q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 ];
|
|
@else # ENDIAN == "big"
|
|
define register offset=0x0300 size=16 [ q15 q14 q13 q12 q11 q10 q9 q8 q7 q6 q5 q4 q3 q2 q1 q0 ];
|
|
@endif # ENDIAN = "big"
|
|
|
|
@endif # SIMD
|
|
|
|
# Define context bits
|
|
# WARNING: when adjusting context keep compiler packing in mind
|
|
# and make sure fields do not span a 32-bit boundary before or
|
|
# after context packing
|
|
define register offset=0x00 size=8 contextreg;
|
|
define context contextreg
|
|
@ifdef T_VARIANT
|
|
TMode = (0,0) # 1 if in Thumb instruction decode mode
|
|
T = (0,0) # exact copy (alias!) of TMode
|
|
LowBitCodeMode = (0,0) # 1 if low bit of instruction address is set on a branch
|
|
ISA_MODE = (0,0) # 1 for Thumb instruction decode mode
|
|
@endif
|
|
LRset = (1,1) noflow # 1 if the instruction right before was a mov lr,pc
|
|
REToverride = (2,2) noflow # 1 if the instruction should be a branch not a return
|
|
CALLoverride = (3,3) noflow # 1 if the call should actually be a jump
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
TEEMode = (4,4) # 1 if in ThumbEE mode, changes some instruction behavior, and makes some instructions invalid
|
|
condit = (5,13) noflow # both base and shift
|
|
cond_mask = (10,13) # base condition
|
|
cond_full = (6,9) # full condition
|
|
cond_true = (9,9) # true if this condition should be tested for true
|
|
cond_base = (6,8) # shift mask for controlling shift
|
|
cond_shft = (9,13) # mask and lower bit of it condition field
|
|
itmode = (5,5) # true if in ITBlock mode
|
|
|
|
@endif
|
|
|
|
# Transient context bits
|
|
counter = (14,18) # 0 to 7 counter (for building variable length register lists)
|
|
# dreg = (17,21) # D register (attached, for building register lists)
|
|
# sreg = (17,21) # S register (attached, for building register lists)
|
|
regNum = (19,23) # D register number (see dreg)
|
|
counter2 = (24,26) # 0 to 7 counter (for building variable length register lists)
|
|
# dreg2 = (25,29) # 2nd D register (attached, for building register lists)
|
|
# sreg2 = (25,29) # 2nd S register (attached, for building register lists)
|
|
reg2Num = (27,31) # 2nd D register number (see dreg2)
|
|
# --- do not allow any field to span 32-bit boundary ---
|
|
regInc = (32,33) # Pair register increment
|
|
ARMcond = (34,34) # ARM conditional instruction
|
|
ARMcondCk = (35,35) # Finished ARM condition check phase
|
|
;
|
|
|
|
define pcodeop count_leading_zeroes;
|
|
define pcodeop coprocessor_function;
|
|
define pcodeop coprocessor_function2;
|
|
define pcodeop coprocessor_load;
|
|
define pcodeop coprocessor_load2;
|
|
define pcodeop coprocessor_loadlong;
|
|
define pcodeop coprocessor_loadlong2;
|
|
define pcodeop coprocessor_moveto;
|
|
define pcodeop coprocessor_moveto2;
|
|
define pcodeop coprocessor_movefromRt;
|
|
define pcodeop coprocessor_movefromRt2;
|
|
define pcodeop coprocessor_movefrom2;
|
|
define pcodeop coprocessor_store;
|
|
define pcodeop coprocessor_store2;
|
|
define pcodeop coprocessor_storelong;
|
|
define pcodeop coprocessor_storelong2;
|
|
define pcodeop software_interrupt;
|
|
define pcodeop software_bkpt;
|
|
define pcodeop software_udf;
|
|
define pcodeop software_hlt;
|
|
define pcodeop software_hvc;
|
|
define pcodeop software_smc;
|
|
|
|
# CPS methods (Version 6)
|
|
define pcodeop setUserMode;
|
|
define pcodeop setFIQMode;
|
|
define pcodeop setIRQMode;
|
|
define pcodeop setSupervisorMode;
|
|
define pcodeop setMonitorMode;
|
|
define pcodeop setAbortMode;
|
|
define pcodeop setUndefinedMode;
|
|
define pcodeop setSystemMode;
|
|
define pcodeop enableIRQinterrupts;
|
|
define pcodeop enableFIQinterrupts;
|
|
define pcodeop enableDataAbortInterrupts;
|
|
define pcodeop disableIRQinterrupts;
|
|
define pcodeop disableFIQinterrupts;
|
|
define pcodeop isFIQinterruptsEnabled;
|
|
define pcodeop isIRQinterruptsEnabled;
|
|
define pcodeop disableDataAbortInterrupts;
|
|
define pcodeop hasExclusiveAccess;
|
|
define pcodeop isCurrentModePrivileged;
|
|
define pcodeop setThreadModePrivileged;
|
|
define pcodeop isThreadMode;
|
|
|
|
define pcodeop jazelle_branch;
|
|
define pcodeop ClearExclusiveLocal;
|
|
define pcodeop HintDebug;
|
|
|
|
define pcodeop DataMemoryBarrier;
|
|
define pcodeop DataSynchronizationBarrier;
|
|
|
|
define pcodeop secureMonitorCall;
|
|
|
|
define pcodeop WaitForEvent;
|
|
define pcodeop WaitForInterrupt;
|
|
|
|
define pcodeop HintYield;
|
|
define pcodeop InstructionSynchronizationBarrier;
|
|
|
|
define pcodeop HintPreloadData;
|
|
define pcodeop HintPreloadDataForWrite;
|
|
define pcodeop HintPreloadInstruction;
|
|
|
|
define pcodeop SignedSaturate;
|
|
define pcodeop SignedDoesSaturate;
|
|
define pcodeop UnsignedSaturate;
|
|
define pcodeop UnsignedDoesSaturate;
|
|
define pcodeop Absolute;
|
|
define pcodeop ReverseBitOrder;
|
|
define pcodeop SendEvent;
|
|
define pcodeop setEndianState;
|
|
|
|
macro affectflags() {
|
|
CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV;
|
|
}
|
|
|
|
macro affect_resflags() {
|
|
ZR = tmpZR; NG = tmpNG;
|
|
}
|
|
|
|
macro SetThumbMode(value) {
|
|
ISAModeSwitch = value;
|
|
TB = ISAModeSwitch;
|
|
}
|
|
|
|
#
|
|
# simple branch, not inter-working
|
|
macro BranchWritePC(addr) {
|
|
pc = addr;
|
|
}
|
|
|
|
#
|
|
# Interworking branch, ARM<->Thumb
|
|
macro BXWritePC(addr) {
|
|
SetThumbMode((addr & 0x1) != 0);
|
|
local tmp = addr & 0xfffffffe;
|
|
pc = tmp;
|
|
}
|
|
|
|
#
|
|
# Branch depends on version
|
|
macro LoadWritePC(addr) {
|
|
@if defined(VERSION_5)
|
|
BXWritePC(addr);
|
|
@else
|
|
BranchWritePC(addr);
|
|
@endif
|
|
}
|
|
|
|
# Branch depends on version
|
|
macro ALUWritePC(addr) {
|
|
@if defined(VERSION_7)
|
|
BXWritePC(addr);
|
|
@else
|
|
BranchWritePC(addr);
|
|
@endif
|
|
}
|
|
|
|
@if defined(T_VARIANT)
|
|
|
|
ItCond: is TMode=1 { }
|
|
CheckInIT_CZNO: is TMode=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; } # in older, arms always affect flags
|
|
CheckInIT_CZN: is TMode=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; } # in older, arms always affect flags
|
|
CheckInIT_ZN: is TMode=1 { ZR = tmpZR; NG = tmpNG; } # in older, arms always affect flags
|
|
|
|
@endif
|
|
|
|
@if defined(VERSION_6T2) || defined(VERSION_7)
|
|
|
|
# conditionals for instruction following IT Block
|
|
thfcc: "eq" is cond_full=0 { local tmp:1 = (ZR!=0); export tmp; }
|
|
thfcc: "ne" is cond_full=1 { local tmp:1 = (ZR==0); export tmp; }
|
|
thfcc: "cs" is cond_full=2 { local tmp:1 = (CY!=0); export tmp; }
|
|
thfcc: "cc" is cond_full=3 { local tmp:1 = (CY==0); export tmp; }
|
|
thfcc: "mi" is cond_full=4 { local tmp:1 = (NG!=0); export tmp; }
|
|
thfcc: "pl" is cond_full=5 { local tmp:1 = (NG==0); export tmp; }
|
|
thfcc: "vs" is cond_full=6 { local tmp:1 = (OV!=0); export tmp; }
|
|
thfcc: "vc" is cond_full=7 { local tmp:1 = (OV==0); export tmp; }
|
|
thfcc: "hi" is cond_full=8 { local tmp:1 = CY && !ZR; export tmp; }
|
|
thfcc: "ls" is cond_full=9 { local tmp:1 = !CY || ZR; export tmp; }
|
|
thfcc: "ge" is cond_full=10 { local tmp:1 = (NG == OV); export tmp; }
|
|
thfcc: "lt" is cond_full=11 { local tmp:1 = (NG != OV); export tmp; }
|
|
thfcc: "gt" is cond_full=12 { local tmp:1 = !ZR && (NG == OV); export tmp; }
|
|
thfcc: "le" is cond_full=13 { local tmp:1 = ZR || (NG != OV); export tmp; }
|
|
thfcc: "al" is cond_full=14 { local tmp:1 = 1; export tmp; } #can happen
|
|
#thfcc: "nv" is cond_full=15 { local tmp:1 = 0; export tmp; } #unpredictable, shouldn't happen
|
|
|
|
|
|
# no ITcondition
|
|
ItCond: is TMode=1 & itmode=0 & cond_mask=0 {}
|
|
# ITBlock then/else case - the condition being tested is modified by the shift below
|
|
ItCond: "."thfcc is TMode=1 & itmode=0 & cond_mask & thfcc [ itmode=1; globalset(inst_next,condit);]
|
|
{ if (!thfcc) goto inst_next; }
|
|
|
|
# last ITBlock then/else case - the condition being tested is modified by the shift below
|
|
ItCond: "."thfcc is TMode=1 & itmode=0 & cond_mask=8 & thfcc
|
|
{ if (!thfcc) goto inst_next; }
|
|
|
|
# certain Thumb instructions don't affect all flags in the IT block
|
|
CheckInIT_CZNO: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_CZNO: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_CZNO: is TMode=1 & itmode=0 & cond_mask=0 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; }
|
|
|
|
CheckInIT_CZN: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_CZN: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_CZN: is TMode=1 & itmode=0 & cond_mask=0 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; }
|
|
|
|
CheckInIT_ZN: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_ZN: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits
|
|
CheckInIT_ZN: is TMode=1 & itmode=0 & cond_mask=0 { ZR = tmpZR; NG = tmpNG; }
|
|
|
|
|
|
:^instruction is itmode=1 & cond_mask=8 & instruction [ condit=0; ] {}
|
|
:^instruction is itmode=1 & cond_mask & instruction [ cond_shft=cond_shft << 1; itmode=0; ]{}
|
|
|
|
@endif # defined(VERSION_6T2) || defined(VERSION_7)
|
|
|
|
@include "ARMinstructions.sinc"
|
|
|
|
# THUMB instructions
|
|
@ifdef T_VARIANT
|
|
@include "ARMTHUMBinstructions.sinc"
|
|
@endif
|