123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994 |
- MODULE ARMDecoder;
- IMPORT SYSTEM, Decoder, Streams, KernelLog;
- CONST
- objFileSuffix = "Oba";
- none = -1;
- (* argument structure *)
- ArgNone = -2;
- ArgImm = 1;
- ArgReg = 2;
- ArgShift = 3;
- ArgRegImm = 11;
- ArgRegReg = 12;
- ArgRegShift = 13;
- ArgRegMem = 14;
- ArgRegRList = 15;
- ArgRegRegImm = 21;
- ArgRegRegReg = 22;
- ArgRegRegShift = 23;
- ArgRegRegMem = 24;
- ArgRegRegRegReg = 31;
- ArgRegRegRegImm = 32;
- ArgRegRegRegShift = 33;
- ArgCProcRegMem = 41;
- ArgCProcImmRegRegRegImm = 42;
- (* registers *)
- FP = 12; SP = 13; LR = 14; PC = 15; CPSR = 16; SPSR = 17;
- (* status register bits *)
- SRegC = 0; SRegX = 1; SRegS = 2; SRegF = 3;
- (* instructions *)
- opUNDEFINED = -2;
- opADC = 1;
- opADD = 2;
- opAND = 3;
- opASR = 4;
- opB = 5;
- opBIC = 6;
- opBKPT = 7;
- opBL = 8;
- opBLX = 9;
- opBX = 10;
- opCDP = 11;
- opCDP2 = 12;
- opCLZ = 13;
- opCMN = 14;
- opCMP = 15;
- opEOR = 16;
- opLDC = 17;
- opLDC2 = 18;
- opLDM = 19;
- opLDR = 20;
- opLDRB = 21;
- opLDRBT = 22;
- opLDRH = 23;
- opLDRSB = 24;
- opLDRSH = 25;
- opLDRT = 26;
- opLSL = 27;
- opLSR = 28;
- opMCR = 29;
- opMCR2 = 30;
- opMLA = 31;
- opMOV = 32;
- opMRC = 33;
- opMRC2 = 34;
- opMRS = 61;
- opMSR = 35;
- opMUL = 36;
- opMVN = 37;
- opORR = 38;
- opROR = 39;
- opRRX = 40;
- opRSB = 41;
- opRSC = 42;
- opSBC = 43;
- opSMLAL = 44;
- opSMULL = 45;
- opSTC = 46;
- opSTC2 = 47;
- opSTM = 48;
- opSTR = 49;
- opSTRB = 50;
- opSTRBT = 51;
- opSTRH = 52;
- opSTRT = 53;
- opSUB = 54;
- opSWI = 55;
- opSWP = 56;
- opSWPB = 62;
- opTEQ = 57;
- opTST = 58;
- opUMLAL = 59;
- opUMULL = 60;
- (* conditions *)
- EQ = 0;
- NE = 1;
- CSHS = 2;
- CCLO = 3;
- MI = 4;
- PL = 5;
- VS = 6;
- VC = 7;
- HI = 8;
- LS = 9;
- GE = 10;
- LT = 11;
- GT = 12;
- LE = 13;
- AL = 14;
- NV = 15;
- (* argument representations *)
- RepInt = 1;
- RepHex = 2;
- RepRelJmp = 10;
- (* immediate reg operations *)
- Lsl = 0;
- LSR = 1;
- Asr = 2;
- Ror = 3;
- RRX = 4;
- (* memory access addressing modes *)
- AddrModeReg = 1;
- AddrModeRegImm = 2;
- AddrModeRegReg = 3;
- AddrModeRegRegScale = 4;
- AddrModeDA = 5;
- AddrModeIA = 6;
- AddrModeDB = 7;
- AddrModeIB = 8;
- RegUpdateNone = 0;
- RegUpdatePre = 1;
- RegUpdatePost = 2;
- TYPE
- ARMArg = OBJECT
- END ARMArg;
- ARMArgImm = OBJECT (ARMArg)
- VAR
- imm, rep : LONGINT;
- PROCEDURE &New *(imm, rep : LONGINT);
- BEGIN
- SELF.imm := imm;
- SELF.rep := rep
- END New;
- END ARMArgImm;
- ARMArgReg = OBJECT (ARMArg)
- VAR
- reg : LONGINT;
- isCReg : BOOLEAN; (* coprocessor register? *)
- sregMask : SET; (* for CPSR, SPSR registers *)
- PROCEDURE &New *(reg : LONGINT);
- BEGIN
- SELF.reg := reg;
- isCReg := FALSE
- END New;
- END ARMArgReg;
- ARMArgRList = OBJECT (ARMArg)
- VAR
- regs : SET;
- addrMode : LONGINT;
- PROCEDURE &New *(regs : SET);
- BEGIN
- SELF.regs := regs;
- END New;
- END ARMArgRList;
- ARMArgMem = OBJECT (ARMArg)
- VAR
- addrMode, reg, regOffs, regScale, shift, immOffs : LONGINT;
- width : LONGINT;
- signed, translation : BOOLEAN;
- regUpdate : LONGINT;
- PROCEDURE &New *(adrMode, reg : LONGINT);
- BEGIN
- SELF.addrMode := adrMode;
- SELF.reg := reg;
- width := 4;
- regUpdate := RegUpdateNone;
- signed := FALSE;
- translation := FALSE
- END New;
- END ARMArgMem;
- ARMArgShift = OBJECT (ARMArg)
- VAR
- shiftImmOrReg, operation : LONGINT;
- reg : BOOLEAN;
- PROCEDURE &New *(operation, shiftImmOrReg : LONGINT; reg : BOOLEAN);
- BEGIN
- SELF.operation := operation;
- SELF.shiftImmOrReg := shiftImmOrReg;
- SELF.reg := reg
- END New;
- END ARMArgShift;
- ARMArgCProc = OBJECT (ARMArg)
- VAR
- cproc : LONGINT;
- PROCEDURE &New *(cproc : LONGINT);
- BEGIN
- SELF.cproc := cproc
- END New;
- END ARMArgCProc;
- ARMOpcode = OBJECT (Decoder.Opcode)
- VAR
- argStructure : LONGINT;
- op, cond : LONGINT;
- ccUpdate : BOOLEAN;
- arg1, arg2, arg3, arg4, arg5, arg6 : ARMArg;
- PROCEDURE &New*(proc : Decoder.ProcedureInfo; stream : Streams.Writer);
- BEGIN
- New^(proc, stream);
- instr := -1;
- ccUpdate := FALSE;
- argStructure := none
- END New;
- PROCEDURE PrintOpcodeBytes (w : Streams.Writer);
- BEGIN
- w.Hex(op, 0)
- END PrintOpcodeBytes;
- PROCEDURE PrintInstruction (w : Streams.Writer);
- VAR str : ARRAY 20 OF CHAR; writeCondition, writeLSMAddrMode : BOOLEAN;
- BEGIN
- writeCondition := TRUE; writeLSMAddrMode := FALSE;
- CASE instr OF
- opADC : str := "ADC"
- | opADD : str := "ADD"
- | opAND : str := "AND"
- | opASR : str := "ASR"
- | opB : str := "B"
- | opBIC : str := "BIC"
- | opBKPT : str := "BKPT"
- | opBL : str := "BL"
- | opBLX : str := "BLX"; writeCondition := FALSE
- | opBX : str := "BX"
- | opCDP : str := "CDP"
- | opCDP2 : str := "CDP2"; writeCondition := FALSE
- | opCLZ : str := "CLZ"
- | opCMN : str := "CMN"
- | opCMP : str := "CMP"
- | opEOR : str := "EOR"
- | opLDC : str := "LDC"
- | opLDC2 : str := "LDC2"; writeCondition := FALSE
- | opLDM : str := "LDM"; writeLSMAddrMode := TRUE
- | opLDR : str := "LDR"
- | opLDRB : str := "LDRB"
- | opLDRBT : str := "LDRBT"
- | opLDRH : str := "LDRH"
- | opLDRSB : str := "LDRSB"
- | opLDRSH : str := "LDRSH"
- | opLDRT : str := "LDRT"
- | opLSL : str := "LSL"
- | opLSR : str := "LSR"
- | opMCR : str := "MCR"
- | opMCR2 : str := "MCR2"; writeCondition := FALSE
- | opMLA : str := "MLA"
- | opMOV : str := "MOV"
- | opMRC : str := "MRC"
- | opMRC2 : str := "MRC2"; writeCondition := FALSE
- | opMRS : str := "MRS"
- | opMSR : str := "MSR"
- | opMUL : str := "MUL"
- | opMVN : str := "MVN"
- | opORR : str := "ORR"
- | opROR : str := "ROR"
- | opRRX : str := "RRX"
- | opRSB : str := "RSB"
- | opRSC : str := "RSC"
- | opSBC : str := "SBC"
- | opSMLAL : str := "SMLAL"
- | opSMULL : str := "SMULL"
- | opSTC : str := "STC"
- | opSTC2 : str := "STC2"; writeCondition := FALSE
- | opSTM : str := "STM"; writeLSMAddrMode := TRUE
- | opSTR : str := "STR"
- | opSTRB : str := "STRB"
- | opSTRBT : str := "STRBT"
- | opSTRH : str := "STRH"
- | opSTRT : str := "STRT"
- | opSUB : str := "SUB"
- | opSWI : str := "SWI"
- | opSWP : str := "SWP"
- | opSWPB : str := "SWPB"
- | opTEQ : str := "TEQ"
- | opTST : str := "TST"
- | opUMLAL : str := "UMLAL"
- | opUMULL : str := "UMULL"
- | opUNDEFINED : str := "{UNDEFINED}"
- ELSE
- KernelLog.String("Unknown instr = "); KernelLog.Int(instr, 0); KernelLog.String(", op = "); KernelLog.Hex(op, -1); KernelLog.Ln;
- str := "[unknown]"
- END;
- w.String(str);
- IF writeCondition THEN PrintCondition(w) END;
- IF writeLSMAddrMode THEN PrintLSMAddrMode(w) END;
- IF ccUpdate THEN w.String(" S")
- ELSIF argStructure = ArgRegMem THEN
- w.String(" ");
- IF arg2(ARMArgMem).signed THEN w.Char('S') END;
- IF arg2(ARMArgMem).width = 1 THEN w.Char('B')
- ELSIF arg2(ARMArgMem).width = 2 THEN w.Char('H')
- END;
- IF arg2(ARMArgMem).translation THEN w.Char('T') END;
- END
- END PrintInstruction;
- PROCEDURE PrintCondition (w : Streams.Writer);
- VAR str : ARRAY 6 OF CHAR;
- BEGIN
- w.Char(' ');
- CASE cond OF
- EQ : str := "EQ"
- | NE : str := "NE"
- | CSHS : str := "CS/HS"
- | CCLO : str := "CC/LO"
- | MI : str := "MI"
- | PL : str := "PL"
- | VS : str := "VS"
- | VC : str := "VC"
- | HI : str := "HI"
- | LS : str := "LS"
- | GE : str := "GE"
- | LT : str := "LT"
- | GT : str := "GT"
- | LE : str := "LE"
- | AL : str := ""
- | NV : str := "NV"
- END;
- w.String(str)
- END PrintCondition;
- PROCEDURE PrintLSMAddrMode (w : Streams.Writer);
- VAR str : ARRAY 6 OF CHAR;
- BEGIN
- ASSERT(argStructure = ArgRegRList);
- w.Char(' ');
- CASE arg2(ARMArgRList).addrMode OF
- AddrModeIA : str := "IA"
- | AddrModeIB : str := "IB"
- | AddrModeDA : str := "DA"
- | AddrModeDB : str := "DB"
- ELSE str := ""
- END;
- w.String(str)
- END PrintLSMAddrMode;
- PROCEDURE PrintArguments (w : Streams.Writer);
- BEGIN
- (* KernelLog.String("*argStructure = "); KernelLog.Int(argStructure, 0); KernelLog.String(", instr = "); KernelLog.Int(instr, 0); KernelLog.Ln; *)
- CASE argStructure OF
- ArgNone :
- | ArgImm : WriteImm(arg1(ARMArgImm), w)
- | ArgReg : WriteReg(arg1(ARMArgReg), w)
- | ArgRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w)
- | ArgRegRList : WriteRegRList(arg1(ARMArgReg), arg2(ARMArgRList), w)
- | ArgRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteImm(arg2(ARMArgImm), w)
- | ArgRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteShift(arg2(ARMArgShift), w)
- | ArgRegMem : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteMem(arg2(ARMArgMem), w)
- | ArgRegRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w)
- | ArgRegRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteImm(arg3(ARMArgImm), w)
- | ArgRegRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteShift(arg3(ARMArgShift), w)
- | ArgRegRegMem : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteMem(arg3(ARMArgMem), w)
- | ArgRegRegRegReg : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteReg(arg4(ARMArgReg), w)
- | ArgRegRegRegImm : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteImm(arg4(ARMArgImm), w)
- | ArgRegRegRegShift : WriteReg(arg1(ARMArgReg), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteShift(arg4(ARMArgShift), w)
- | ArgCProcRegMem : WriteCProc(arg1(ARMArgCProc), w); w.String(", "); WriteReg(arg2(ARMArgReg), w); w.String(", "); WriteMem(arg3(ARMArgMem), w)
- | ArgCProcImmRegRegRegImm : WriteCProc(arg1(ARMArgCProc), w); w.String(", "); WriteImm(arg2(ARMArgImm), w); w.String(", "); WriteReg(arg3(ARMArgReg), w); w.String(", "); WriteReg(arg4(ARMArgReg), w); w.String(", "); WriteReg(arg5(ARMArgReg), w); w.String(", "); WriteImm(arg2(ARMArgImm), w)
- ELSE
- KernelLog.String("argStructure = "); KernelLog.Int(argStructure, 0); KernelLog.Ln;
- w.String("{argStructure not specified!}")
- END
- END PrintArguments;
- PROCEDURE WriteImm (immArg : ARMArgImm; w : Streams.Writer);
- PROCEDURE WriteHex;
- VAR absImm : LONGINT;
- BEGIN
- absImm := immArg.imm;
- IF immArg.rep = RepRelJmp THEN
- (* add opcode position and length of full opcode to immediate argument value *)
- INC(absImm, LONGINT(offset + 4))
- END;
- Hex(absImm, w)
- END WriteHex;
- BEGIN
- IF immArg.rep = RepInt THEN
- w.Int(immArg.imm, 0)
- ELSIF immArg.rep = RepHex THEN
- WriteHex
- ELSE
- w.Int(immArg.imm, 0);
- w.String(" (");
- WriteHex;
- w.Char(')')
- END
- END WriteImm;
- PROCEDURE WriteReg (regArg : ARMArgReg; w : Streams.Writer);
- BEGIN
- IF regArg.isCReg THEN
- w.String("CR"); w.Int(regArg.reg, 0)
- ELSE
- WriteRegSymbol(regArg.reg, w);
- IF regArg.reg >= CPSR THEN
- IF regArg.sregMask * {SRegC} # {} THEN w.String("c") END;
- IF regArg.sregMask * {SRegX} # {} THEN w.String("x") END;
- IF regArg.sregMask * {SRegS} # {} THEN w.String("s") END;
- IF regArg.sregMask * {SRegF} # {} THEN w.String("f") END
- END
- END
- END WriteReg;
- PROCEDURE WriteRegSymbol (reg : LONGINT; w : Streams.Writer);
- BEGIN
- CASE reg OF
- FP : w.String("FP")
- | SP : w.String("SP")
- | LR : w.String("LR")
- | PC : w.String("PC")
- | CPSR : w.String("CPSR")
- | SPSR : w.String("SPSR")
- ELSE
- w.Char('R'); w.Int(reg, 0)
- END
- END WriteRegSymbol;
- PROCEDURE WriteShiftSymbol (op : LONGINT; w : Streams.Writer);
- BEGIN
- CASE op OF
- Lsl : w.String("LSL ")
- | LSR : w.String("LSR ")
- | Asr : w.String("ASR ")
- | Ror : w.String("ROR ")
- | RRX : w.String("RRX ")
- END;
- END WriteShiftSymbol;
- PROCEDURE WriteShift (shiftArg : ARMArgShift; w : Streams.Writer);
- BEGIN
- WriteShiftSymbol(shiftArg.operation, w);
- IF shiftArg.operation # RRX THEN
- IF shiftArg.reg THEN
- ASSERT(shiftArg.shiftImmOrReg < CPSR);
- WriteRegSymbol(shiftArg.shiftImmOrReg, w)
- ELSE
- w.Char('#');
- Hex(shiftArg.shiftImmOrReg, w)
- END
- END
- END WriteShift;
- PROCEDURE WriteMem (memArg : ARMArgMem; w : Streams.Writer);
- PROCEDURE WriteEnd;
- BEGIN
- IF memArg.regUpdate # RegUpdatePost THEN
- w.Char("]");
- IF memArg.regUpdate = RegUpdatePre THEN w.Char('!') END
- END
- END WriteEnd;
- BEGIN
- w.Char('[');
- WriteRegSymbol(memArg.reg, w);
- IF memArg.regUpdate = RegUpdatePost THEN w.Char(']') END;
- CASE memArg.addrMode OF
- AddrModeReg : w.Char(']')
- | AddrModeRegImm :
- w.String(", #");
- IF memArg.immOffs < 0 THEN w.Char('-'); Hex(-memArg.immOffs, w) ELSE Hex(memArg.immOffs, w) END;
- WriteEnd
- | AddrModeRegReg :
- w.String(", "); WriteRegSymbol(memArg.regOffs, w); WriteEnd
- | AddrModeRegRegScale : w.String(", "); WriteRegSymbol(memArg.regOffs, w); w.String(", "); WriteShiftSymbol(memArg.shift, w); w.String(" #"); w.Int(memArg.regScale, 0); WriteEnd
- END
- END WriteMem;
- PROCEDURE WriteRegRList (regArg : ARMArgReg; rListArg : ARMArgRList; w : Streams.Writer);
- VAR i, lastStart : LONGINT; notFirst : BOOLEAN;
- PROCEDURE PrintRegs (start, end : LONGINT);
- BEGIN
- IF start >= 0 THEN
- IF notFirst THEN w.String(", ") END;
- IF start < end THEN (* print range *)
- WriteRegSymbol(start, w); w.String(" - "); WriteRegSymbol(end, w)
- ELSE (* print single reg *)
- WriteRegSymbol(start, w)
- END;
- notFirst := TRUE
- END
- END PrintRegs;
- BEGIN
- WriteRegSymbol(regArg.reg, w);
- IF rListArg.addrMode # none THEN w.Char('!') END;
- w.String(", {");
- lastStart := -1;
- notFirst := FALSE;
- FOR i := 0 TO PC DO
- IF rListArg.regs * {i} # {} THEN IF lastStart < 0 THEN lastStart := i END
- ELSE
- PrintRegs(lastStart, i-1); lastStart := -1
- END;
- END;
- PrintRegs(lastStart, PC);
- w.Char('}')
- END WriteRegRList;
- PROCEDURE WriteCProc (cProcArg : ARMArgCProc; w : Streams.Writer);
- BEGIN
- w.Char('p'); w.Int(cProcArg.cproc, 0)
- END WriteCProc;
- END ARMOpcode;
- ARMDecoder = OBJECT (Decoder.Decoder)
- VAR
- bit24To27, bit20To23, bit16To19, bit12To15, bit8To11, bit4To7, bit0To3 : LONGINT;
- PROCEDURE NewOpcode() : Decoder.Opcode;
- VAR
- opcode : ARMOpcode;
- BEGIN
- NEW(opcode, currentProc, outputStreamWriter);
- RETURN opcode
- END NewOpcode;
- PROCEDURE DecodeThis(opcode : Decoder.Opcode);
- VAR
- armOpcode : ARMOpcode;
- opSet : SET;
- code, category : LONGINT;
- BEGIN
- armOpcode := opcode(ARMOpcode);
- armOpcode.op := ReadLInt();
- IF bigEndian THEN SwapBytes(armOpcode.op) END;
- opSet := SYSTEM.VAL(SET, armOpcode.op);
- (* KernelLog.String("op = "); KernelLog.Hex(armOpcode.op, 0); KernelLog.String(" -> "); *)
- code := armOpcode.op;
- bit0To3 := code MOD 10H; code := code DIV 10H; (* split instruction *)
- bit4To7 := code MOD 10H; code := code DIV 10H;
- bit8To11 := code MOD 10H; code := code DIV 10H;
- bit12To15 := code MOD 10H; code := code DIV 10H;
- bit16To19 := code MOD 10H; code := code DIV 10H;
- bit20To23 := code MOD 10H; code := code DIV 10H;
- bit24To27 := code MOD 10H; code := code DIV 10H;
- armOpcode.cond := code MOD 10H;
- category := bit24To27 DIV 2;
- IF armOpcode.cond = 15 THEN
- IF category = 5 THEN
- BranchToThumb(armOpcode, armOpcode.op);
- RETURN
- ELSIF ((category = 7) & (bit24To27 = 0EH)) OR (category = 6) THEN (* not undefined *)
- ELSE
- armOpcode.instr := opUNDEFINED;
- armOpcode.argStructure := ArgNone;
- RETURN
- END
- END;
- CASE category OF
- 0 :
- IF (opSet * {4, 7}) = {4, 7} THEN
- MultipliesExtraLS(armOpcode)
- ELSIF (opSet * {20, 23, 24}) = {24} THEN Miscellaneous(armOpcode)
- ELSE DataProcessing(armOpcode)
- END
- | 1 :
- IF (opSet * {20, 21, 23, 24}) = {21, 24} THEN
- SRegTransfer(armOpcode)
- ELSIF (opSet * {20, 21, 23, 24}) = {24} THEN
- armOpcode.instr := opUNDEFINED;
- armOpcode.argStructure := ArgNone
- ELSE DataProcessing(armOpcode)
- END
- | 2 : LoadStore(armOpcode)
- | 3 :
- IF (opSet * {4}) = {4} THEN
- armOpcode.instr := opUNDEFINED;
- armOpcode.argStructure := ArgNone
- ELSE LoadStore(armOpcode)
- END
- | 4 : LoadStoreMultiple(armOpcode)
- | 5 : Branch(armOpcode)
- | 6 : CoprocLoadStoreDRegTransfer(armOpcode)
- | 7 : KernelLog.String("check2"); KernelLog.Ln;
- IF (opSet * {24}) = {24} THEN SoftwareInterrupt(armOpcode)
- ELSIF (opSet * {4}) = {4} THEN CoprocRegTransfer(armOpcode)
- ELSE CoprocDataProcessing(armOpcode)
- END
- END
- END DecodeThis;
- PROCEDURE DecodeShifterOperand(op : LONGINT; VAR argStructure : LONGINT; VAR arg1, arg2 : ARMArg);
- VAR
- Rm, shiftImmOrReg, operation, mode : LONGINT;
- regOp : BOOLEAN;
- regArg : ARMArgReg;
- immArg : ARMArgImm;
- shiftArg : ARMArgShift;
- BEGIN
- IF (SYSTEM.VAL(SET, op) * {25}) = {25} THEN (* I Bit *)
- argStructure := ArgImm;
- NEW(immArg, ROT(op MOD 100H, -2*bit8To11), RepHex); arg1 := immArg;
- ELSE
- Rm := op MOD 10H;
- NEW(regArg, Rm); arg1 := regArg;
- argStructure := ArgRegShift;
- mode := bit4To7 MOD 8; (* type of register addressing mode *)
- IF mode = 0 THEN (* Register / Logical shift left by immediate *)
- shiftImmOrReg := (op MOD 1000H) DIV 80H;
- IF shiftImmOrReg = 0 THEN argStructure := ArgReg
- ELSE
- NEW(shiftArg, Lsl, shiftImmOrReg, FALSE); arg2 := shiftArg
- END
- ELSIF ((op MOD 1000H) DIV 10H) = 6 THEN (* rotate right with extend *)
- NEW(shiftArg, RRX, 0, FALSE); arg2 := shiftArg
- ELSE
- CASE mode OF
- 1 : operation := Lsl
- | 2,3 : operation := LSR
- | 4,5 : operation := Asr
- | 6,7 : operation := Ror
- END;
- IF ODD(mode) THEN
- regOp := TRUE;
- shiftImmOrReg := bit8To11
- ELSE
- regOp := FALSE;
- shiftImmOrReg := (op MOD 1000H) DIV 80H
- END;
- NEW(shiftArg, operation, shiftImmOrReg, regOp); arg2 := shiftArg
- END
- END
- END DecodeShifterOperand;
- PROCEDURE DataProcessing (opcode : ARMOpcode);
- VAR SBit : BOOLEAN; Rn, Rd, type : LONGINT;
- regArg : ARMArgReg; argSh1, argSh2 : ARMArg;
- shStruct : LONGINT;
- BEGIN
- CASE (opcode.op MOD 2000000H) DIV 200000H OF (* opcode *)
- 0 : opcode.instr := opAND; type := 3
- | 1 : opcode.instr := opEOR; type := 3
- | 2 : opcode.instr := opSUB; type := 3
- | 3 : opcode.instr := opRSB; type := 3
- | 4 : opcode.instr := opADD; type := 3
- | 5 : opcode.instr := opADC; type := 3
- | 6 : opcode.instr := opSBC; type := 3
- | 7 : opcode.instr := opRSC; type := 3
- | 8 : opcode.instr := opTST; type := 2
- | 9 : opcode.instr := opTEQ; type := 2
- | 10 : opcode.instr := opCMP; type := 2
- | 11 : opcode.instr := opCMN; type := 2
- | 12 : opcode.instr := opORR; type := 3
- | 13 : opcode.instr := opMOV; type := 1
- | 14 : opcode.instr := opBIC; type := 3
- | 15 : opcode.instr := opMVN; type := 1
- END;
- DecodeShifterOperand(opcode.op, shStruct, argSh1, argSh2);
- IF (SYSTEM.VAL(SET, opcode.op) * {20}) = {20} THEN SBit := TRUE ELSE SBit := FALSE END;
- opcode.ccUpdate := SBit & (type # 2);
- Rn := bit16To19;
- Rd := bit12To15;
- IF (type = 1) OR (type = 2) THEN
- opcode.argStructure := shStruct + 10;
- IF type = 1 THEN NEW(regArg, Rd) ELSE NEW(regArg, Rn) END;
- opcode.arg1 := regArg; opcode.arg2 := argSh1; opcode.arg3 := argSh2
- ELSIF type = 3 THEN
- opcode.argStructure := shStruct + 20;
- NEW(regArg, Rd); opcode.arg1 := regArg;
- NEW(regArg, Rn); opcode.arg2 := regArg;
- opcode.arg3 := argSh1; opcode.arg4 := argSh2
- END
- END DataProcessing;
- PROCEDURE Miscellaneous (opcode : ARMOpcode);
- VAR regArg : ARMArgReg; immArg : ARMArgImm;
- BEGIN
- CASE bit4To7 MOD 2 OF
- 0 : SRegTransfer(opcode)
- | 1 :
- IF bit20To23 = 6 THEN
- opcode.instr := opCLZ;
- opcode.argStructure := ArgRegReg;
- NEW(regArg, bit12To15); opcode.arg1 := regArg;
- NEW(regArg, bit0To3); opcode.arg2 := regArg
- ELSIF LSH(opcode.op, -20) = 0E12H THEN
- IF bit4To7 = 7 THEN
- opcode.instr := opBKPT;
- NEW(immArg, (((opcode.op MOD 100000) DIV 100H) * 10H) + (opcode.op MOD 10H), RepHex);
- opcode.argStructure := ArgImm;
- opcode.arg1 := immArg
- ELSIF bit4To7 = 1 THEN
- opcode.instr := opBX;
- NEW(regArg, bit0To3); opcode.arg1 := regArg;
- opcode.argStructure := ArgReg
- END
- END
- END
- END Miscellaneous;
- PROCEDURE MultipliesExtraLS (opcode : ARMOpcode);
- VAR op1: LONGINT;
- regA, regB, regC, regD : ARMArgReg; memArg : ARMArgMem;
- argSh1, argSh2 : ARMArg;
- shStruct : LONGINT;
- BEGIN
- op1 := bit20To23 DIV 2;
- opcode.ccUpdate := (bit20To23 MOD 2) = 1; (* S bit set? *)
- NEW(regA, bit16To19);
- NEW(regB, bit12To15);
- NEW(regC, bit8To11);
- NEW(regD, bit0To3);
- IF bit24To27 = 1 THEN (* SWP/SWPB *)
- NEW(memArg, AddrModeReg, regA.reg);
- opcode.argStructure := ArgRegRegMem;
- opcode.arg1 := regB; opcode.arg2 := regD; opcode.arg3 := memArg;
- IF bit20To23 = 0 THEN opcode.instr := opSWP ELSE opcode.instr := opSWPB END
- ELSE
- opcode.argStructure := ArgRegRegRegReg;
- opcode.arg1 := regB; opcode.arg2 := regA; opcode.arg3 := regD; opcode.arg4 := regC;
- CASE op1 OF
- 0 : opcode.instr := opMUL; opcode.argStructure := ArgRegRegReg; opcode.arg1 := regA; opcode.arg2 := regD; opcode.arg3 := regC
- | 1 : opcode.instr := opMLA; opcode.arg1 := regA; opcode.arg2 := regD; opcode.arg3 := regC; opcode.arg4 := regB
- | 3 : opcode.instr := opRSB; opcode.arg1 := regB; opcode.arg2 := regA; DecodeShifterOperand(opcode.op, shStruct, argSh1, argSh2); opcode.argStructure := shStruct + 20; opcode.arg3 := argSh1; opcode.arg4 := argSh2
- | 4 : opcode.instr := opUMULL
- | 5 : opcode.instr := opUMLAL
- | 6 : opcode.instr := opSMULL
- | 7 : opcode.instr := opSMLAL
- END
- END
- END MultipliesExtraLS;
- PROCEDURE SRegTransfer (opcode : ARMOpcode);
- VAR regArg : ARMArgReg; immArg : ARMArgImm;
- BEGIN
- opcode.argStructure := ArgRegReg;
- IF (bit20To23 DIV 4) = 1 THEN NEW(regArg, SPSR) ELSE NEW(regArg, CPSR) END;
- IF (bit20To23 MOD 4) # 2 THEN
- opcode.instr := opMRS;
- opcode.arg2 := regArg;
- NEW(regArg, bit12To15); opcode.arg1 := regArg
- ELSE
- opcode.instr := opMSR;
- regArg.sregMask := SYSTEM.VAL(SET, bit16To19);
- opcode.arg1 := regArg;
- IF (bit24To27 DIV 2) = 1 THEN (* immediate operand *)
- NEW(immArg, ROT(opcode.op MOD 100H, -2*bit8To11), RepHex); (* 8 bit imm rotated by rotate imm *)
- opcode.arg2 := immArg
- ELSE NEW(regArg, bit0To3); opcode.arg2 := regArg
- END
- END
- END SRegTransfer;
- PROCEDURE LoadStore (opcode : ARMOpcode);
- VAR regArg : ARMArgReg; memArg : ARMArgMem;
- P, L, W, B, U : BOOLEAN;
- offset12 : LONGINT;
- BEGIN
- opcode.argStructure := ArgRegMem;
- NEW(regArg, bit12To15); opcode.arg1 := regArg;
- P := bit24To27 MOD 2 = 1;
- L := bit20To23 MOD 2 = 1;
- W := (bit20To23 MOD 4) DIV 2 = 1;
- B := (bit20To23 MOD 8) DIV 4 = 1;
- U := bit20To23 DIV 8 = 1;
- offset12 := opcode.op MOD 1000H;
- (* determine memory location and addressing mode *)
- IF (bit24To27 DIV 2) = 2 THEN (* immediate offset/index *)
- IF offset12 = 0 THEN NEW(memArg, AddrModeReg, bit16To19)
- ELSE
- NEW(memArg, AddrModeRegImm, bit16To19);
- IF U THEN memArg.immOffs := offset12 ELSE memArg.immOffs := -offset12 END
- END
- ELSE (* register offset/index *)
- IF (bit4To7 = 0) & (bit8To11 = 0) THEN
- NEW(memArg, AddrModeRegReg, bit16To19); memArg.regOffs := bit0To3
- ELSE
- NEW(memArg, AddrModeRegRegScale, bit16To19); memArg.regOffs := bit0To3;
- memArg.shift := (bit4To7 MOD 8) DIV 2;
- memArg.regScale := (opcode.op MOD 1000H) DIV 80H
- END
- END;
- IF L THEN opcode.instr := opLDR ELSE opcode.instr := opSTR END;
- IF ~P THEN (* P = 0, post index addressing *)
- IF memArg.addrMode # AddrModeReg THEN memArg.regUpdate := RegUpdatePost END;
- memArg.immOffs := opcode.op MOD 1000H;
- ELSE (* P = 1, offset or pre-indexed addressing *)
- IF W THEN (* base register update *)
- memArg.regUpdate := RegUpdatePre;
- END
- END;
- IF W THEN memArg.translation := TRUE END;
- IF B THEN memArg.width := 1 END;
- opcode.arg2 := memArg
- END LoadStore;
- PROCEDURE LoadStoreMultiple (opcode : ARMOpcode);
- VAR regArg : ARMArgReg; regListArg : ARMArgRList;
- P, U, S, W, L : BOOLEAN;
- BEGIN
- P := bit24To27 MOD 2 = 1;
- U := bit20To23 DIV 8 = 1;
- S := (bit20To23 MOD 8) DIV 4 = 1;
- W := (bit20To23 MOD 4) DIV 2 = 1;
- L := bit20To23 MOD 2 = 1;
- IF L THEN opcode.instr := opLDM ELSE opcode.instr := opSTM END;
- NEW(regArg, bit16To19);
- NEW(regListArg, SYSTEM.VAL(SET, opcode.op MOD 10000H));
- IF W THEN
- IF P THEN IF U THEN regListArg.addrMode := AddrModeIB ELSE regListArg.addrMode := AddrModeDB END
- ELSE IF U THEN regListArg.addrMode := AddrModeIA ELSE regListArg.addrMode := AddrModeDA END
- END
- ELSE regListArg.addrMode := none END;
- opcode.argStructure := ArgRegRList;
- opcode.arg1 := regArg;
- opcode.arg2 := regListArg
- END LoadStoreMultiple;
- PROCEDURE Branch (opcode : ARMOpcode);
- VAR immArg : ARMArgImm;
- BEGIN
- IF (SYSTEM.VAL(SET, opcode.op) * {24}) = {24} THEN opcode.instr := opBL
- ELSE opcode.instr := opB
- END;
- opcode.argStructure := ArgImm;
- NEW(immArg, (opcode.op MOD 1000000H), RepRelJmp);
- SignExtension(immArg.imm, 24);
- immArg.imm := (immArg.imm + 1) *4;
- opcode.arg1 := immArg
- END Branch;
- PROCEDURE BranchToThumb (opcode : ARMOpcode; op : LONGINT);
- VAR sImmed24, targetAddr : LONGINT; immArg : ARMArgImm; regArg : ARMArgReg;
- BEGIN
- opcode.instr := opBLX;
- IF opcode.cond = 15 THEN
- sImmed24 := opcode.op MOD 1000000H;
- targetAddr := (bit24To27 MOD 2)*2 + ASH(LSH(sImmed24, 8), -6); (* sign extend *)
- NEW(immArg, targetAddr, RepRelJmp); opcode.arg1 := immArg;
- opcode.argStructure := ArgImm
- ELSE
- NEW(regArg, bit0To3); opcode.arg1 := regArg;
- opcode.argStructure := ArgReg
- END
- END BranchToThumb;
- PROCEDURE CoprocLoadStoreDRegTransfer (opcode : ARMOpcode);
- VAR cProcArg : ARMArgCProc; memArg : ARMArgMem; regArg : ARMArgReg;
- P, U, W, mul4 : BOOLEAN;
- BEGIN
- IF (bit20To23 MOD 2) = 1 THEN opcode.instr := opLDC ELSE opcode.instr := opSTC END;
- P := (bit24To27 MOD 2) = 1; (* P bit *)
- U := (bit20To23 DIV 8) = 1; (* U bit *)
- W := ((bit20To23 MOD 4) DIV 2) = 1; (* W bit *)
- mul4 := TRUE;
- opcode.argStructure := ArgCProcRegMem;
- NEW(memArg, AddrModeRegImm, bit16To19);
- IF P THEN
- memArg.regUpdate := RegUpdatePost;
- IF ~W THEN mul4 := FALSE END (* this is the option argument, therefore it is not multiplied by 4, but represented the same way like a post update offset *)
- ELSE
- IF W THEN memArg.regUpdate := RegUpdatePre
- ELSE memArg.regUpdate := RegUpdateNone
- END
- END;
- IF U THEN memArg.immOffs := (opcode.op MOD 100H) ELSE memArg.immOffs := - (opcode.op MOD 100H) END;
- IF mul4 THEN memArg.immOffs := memArg.immOffs * 4 END;
- NEW(cProcArg, bit8To11); opcode.arg1 := cProcArg;
- NEW(regArg, bit12To15); regArg.isCReg := TRUE;
- opcode.arg1 := cProcArg; opcode.arg2 := regArg; opcode.arg3 := memArg
- END CoprocLoadStoreDRegTransfer;
- PROCEDURE CoprocDataProcessing (opcode : ARMOpcode);
- BEGIN
- CoprocRegTransfer(opcode);
- IF opcode.cond = 15 THEN opcode.instr := opCDP2 ELSE opcode.instr := opCDP END;
- opcode.arg2(ARMArgImm).imm := bit20To23
- END CoprocDataProcessing;
- PROCEDURE CoprocRegTransfer (opcode : ARMOpcode);
- VAR immArg : ARMArgImm; regArg : ARMArgReg; cProcArg : ARMArgCProc;
- BEGIN
- IF (bit20To23 MOD 2) = 1 THEN
- IF opcode.cond = 15 THEN opcode.instr := opMRC2 ELSE opcode.instr := opMRC END
- ELSE
- IF opcode.cond = 15 THEN opcode.instr := opMCR2 ELSE opcode.instr := opMCR END
- END;
- opcode.argStructure := ArgCProcImmRegRegRegImm;
- NEW(cProcArg, bit8To11); opcode.arg1 := cProcArg;
- NEW(immArg, bit20To23 DIV 2, RepInt); opcode.arg2 := immArg; (* opcode-1 *)
- NEW(regArg, bit12To15); opcode.arg3 := regArg;
- NEW(regArg, bit16To19); regArg.isCReg := TRUE; opcode.arg4 := regArg;
- NEW(regArg, bit0To3); regArg.isCReg := TRUE; opcode.arg5 := regArg;
- NEW(immArg, bit4To7 DIV 2, RepInt); opcode.arg6 := immArg
- END CoprocRegTransfer;
- PROCEDURE SoftwareInterrupt (opcode : ARMOpcode);
- VAR immArg : ARMArgImm;
- BEGIN
- NEW(immArg, opcode.op MOD 1000000H, RepHex);
- opcode.instr := opSWI;
- opcode.argStructure := ArgImm;
- opcode.arg1 := immArg
- END SoftwareInterrupt;
- PROCEDURE SignExtension (VAR x : LONGINT; length : LONGINT);
- BEGIN
- ASSERT((length > 0) & (length <= 32));
- x := LSH(x, 32-length);
- x := ASH(x, length-32)
- END SignExtension;
- END ARMDecoder;
- VAR
- bigEndian : BOOLEAN;
- PROCEDURE SetBigEndian*;
- BEGIN
- bigEndian := TRUE;
- END SetBigEndian;
- PROCEDURE SetLittleEndian*;
- BEGIN
- bigEndian := FALSE;
- END SetLittleEndian;
- PROCEDURE Hex(n: LONGINT; w : Streams.Writer); (* procedure from PCARMDecoder.Mod *)
- VAR i, j: INTEGER; s, t : ARRAY 10 OF CHAR;
- BEGIN
- i := 0;
- REPEAT
- IF n MOD 10H < 10 THEN s[i] := CHR(n MOD 10H +ORD("0")) ELSE s[i] := CHR(n MOD 10H - 10 + ORD("A")) END;
- n := n DIV 10H MOD 10000000H; INC(i);
- UNTIL n = 0;
- j := 0;
- WHILE i>0 DO DEC(i); t[j] := s[i]; INC(j) END; t[j]:="H"; t[j+1] := 0X;
- w.String(t)
- END Hex;
- PROCEDURE SwapBytes(VAR code: LONGINT);
- TYPE Opcode = ARRAY 4 OF CHAR;
- VAR opcode: Opcode;
- tmp: CHAR;
- BEGIN
- opcode := SYSTEM.VAL(Opcode, code);
- tmp := opcode[0]; opcode[0] := opcode[3]; opcode[3] := tmp;
- tmp := opcode[1]; opcode[1] := opcode[2]; opcode[2] := tmp;
- code := SYSTEM.VAL(LONGINT, opcode);
- END SwapBytes;
- PROCEDURE ARMDecoderFactory (reader : Streams.Reader) : Decoder.Decoder;
- VAR
- armDecoder : ARMDecoder;
- BEGIN
- NEW(armDecoder, reader);
- RETURN armDecoder
- END ARMDecoderFactory;
- PROCEDURE CodeScaleCallback(VAR codeSize: LONGINT);
- BEGIN
- codeSize := codeSize * 4
- END CodeScaleCallback;
- PROCEDURE Init*;
- BEGIN
- Decoder.RegisterDecoder("Oba", ARMDecoderFactory, CodeScaleCallback);
- KernelLog.String("ARMDecoder installed."); KernelLog.Ln;
- END Init;
- BEGIN
- bigEndian := FALSE;
- END ARMDecoder.
|