update to ida 7.6, add builds
This commit is contained in:
4253
idasdk76/module/h8/ana.cpp
Normal file
4253
idasdk76/module/h8/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1469
idasdk76/module/h8/emu.cpp
Normal file
1469
idasdk76/module/h8/emu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
332
idasdk76/module/h8/h8.cfg
Normal file
332
idasdk76/module/h8/h8.cfg
Normal file
@@ -0,0 +1,332 @@
|
||||
;
|
||||
; This file describes the standard address names for Hitachi H8
|
||||
;
|
||||
|
||||
.default H8/3644
|
||||
|
||||
.H8/3644
|
||||
TIER 0xF770
|
||||
TCSRX 0xF771
|
||||
FRCH 0xF772
|
||||
FRCL 0xF773
|
||||
OCRAH 0xF774
|
||||
OCRAL 0xF775
|
||||
TCRX 0xF776
|
||||
TOCR 0xF777
|
||||
ICRAH 0xF778
|
||||
ICRAL 0xF779
|
||||
ICRBH 0xF77A
|
||||
ICRBL 0xF77B
|
||||
ICRCH 0xF77C
|
||||
ICRCL 0xF77D
|
||||
ICRDH 0xF77E
|
||||
ICRDL 0xF77F
|
||||
FLMCR 0xFF80
|
||||
EBR1 0xFF82
|
||||
EBR2 0xFF83
|
||||
SCR1 0xFFA0
|
||||
SCSR1 0xFFA1
|
||||
SDRU 0xFFA2
|
||||
SDRL 0xFFA3
|
||||
SMR 0xFFA8
|
||||
BRR 0xFFA9
|
||||
SCR3 0xFFAA
|
||||
TDR 0xFFAB
|
||||
SSR 0xFFAC
|
||||
RDR 0xFFAD
|
||||
TMA 0xFFB0
|
||||
TCA 0xFFB1
|
||||
TMB1 0xFFB2
|
||||
TCB1 0xFFB3
|
||||
TCRV0 0xFFB8
|
||||
TCSRV 0xFFB9
|
||||
TCORA 0xFFBA
|
||||
TCORB 0xFFBB
|
||||
TCNTV 0xFFBC
|
||||
TCRV1 0xFFBD
|
||||
TCSRW 0xFFBE
|
||||
TCW 0xFFBF
|
||||
AMR 0xFFC4
|
||||
ADRR 0xFFC5
|
||||
ADSR 0xFFC6
|
||||
PWCR 0xFFD0
|
||||
PWDRU 0xFFD1
|
||||
PWDRL 0xFFD2
|
||||
PDR1 0xFFD4
|
||||
PDR2 0xFFD5
|
||||
PDR3 0xFFD6
|
||||
PDR5 0xFFD8
|
||||
PDR6 0xFFD9
|
||||
PDR7 0xFFDA
|
||||
PDR8 0xFFDB
|
||||
PDR9 0xFFDC
|
||||
PDRB 0xFFDD
|
||||
PCR1 0xFFE4
|
||||
PCR2 0xFFE5
|
||||
PCR3 0xFFE6
|
||||
PCR5 0xFFE8
|
||||
PCR6 0xFFE9
|
||||
PCR7 0xFFEA
|
||||
PCR8 0xFFEB
|
||||
PCR9 0xFFEC
|
||||
PUCR1 0xFFED
|
||||
PUCR3 0xFFEE
|
||||
PUCR5 0xFFEF
|
||||
SYSCR1 0xFFF0
|
||||
SYSCR2 0xFFF1
|
||||
IEGR1 0xFFF2
|
||||
IEGR2 0xFFF3
|
||||
IENR1 0xFFF4
|
||||
IENR2 0xFFF5
|
||||
IENR3 0xFFF6
|
||||
IRR1 0xFFF7
|
||||
IRR2 0xFFF8
|
||||
IRR3 0xFFF9
|
||||
PMR1 0xFFFC
|
||||
PMR3 0xFFFD
|
||||
PMR7 0xFFFF
|
||||
|
||||
.H8S/2215R
|
||||
UCTLR 0xC00080
|
||||
UTSTRA 0xC00081
|
||||
UDMAR 0xC00082
|
||||
UDRR 0xC00083
|
||||
UTRG0 0xC00084
|
||||
UFCLR0 0xC00086
|
||||
UESTL0 0xC00088
|
||||
UESTL1 0xC00089
|
||||
UEDR0s 0xC00090
|
||||
UEDR0i 0xC00094
|
||||
UEDR0o 0xC00098
|
||||
UEDR3 0xC0009c
|
||||
UEDR1 0xC000a0
|
||||
UEDR2 0xC000a4
|
||||
UESZ0o 0xC000bc
|
||||
UESZ2 0xC000bd
|
||||
UIFR0 0xC000c0
|
||||
UIFR1 0xC000c1
|
||||
UIFR3 0xC000c3
|
||||
UIER0 0xC000c4
|
||||
UIER1 0xC000c5
|
||||
UIER3 0xC000c7
|
||||
UISR0 0xC000c8
|
||||
UISR1 0xC000c9
|
||||
UISR3 0xC000cb
|
||||
UDSR 0xC000cc
|
||||
UCVR 0xC000cf
|
||||
UTSRH 0xC000d0
|
||||
UTSRL 0xC000d1
|
||||
UTSTR0 0xC000f0
|
||||
UTSTR1 0xC000f1
|
||||
UTSTR2 0xC000f2
|
||||
UTSTRB 0xC000fb
|
||||
UTSTRC 0xC000fc
|
||||
UTSTRD 0xC000fd
|
||||
UTSTRE 0xC000fe
|
||||
UTSTRF 0xC000ff
|
||||
|
||||
DADR_0 0xFFFDAC D/A data register 0
|
||||
DADR_1 0xFFFDAD D/A data register 1
|
||||
DACR 0xFFFDAE D/A control register
|
||||
|
||||
SCRX 0xFFFDB4 Serial control register X
|
||||
|
||||
SBYCR 0xFFFDE4 Standby control register
|
||||
SYSCR 0xFFFDE5 System control register
|
||||
SCKCR 0xFFFDE6 System clock control register
|
||||
MDCR 0xFFFDE7 Mode control register
|
||||
MSTPCRA 0xFFFDE8 Module stop control register A
|
||||
MSTPCRB 0xFFFDE9 Module stop control register B
|
||||
MSTPCRC 0xFFFDEA Module stop control register C
|
||||
|
||||
PFCR 0xFFFDEB Pin function control register
|
||||
LPWRCR 0xFFFDEC Low power control register
|
||||
|
||||
SEMRA_0 0xFFFDF8 Serial extended mode register A_0
|
||||
SEMRB_0 0xFFFDF9 Serial extended mode register B_0
|
||||
|
||||
ISCRH 0xFFFE12 IRQ sense control register H
|
||||
ISCRL 0xFFFE13 IRQ sense control register L
|
||||
IER 0xFFFE14 IRQ enable register
|
||||
ISR 0xFFFE15 IRQ status register
|
||||
|
||||
DTCERA 0xFFFE16 DTC enable register A
|
||||
DTCERB 0xFFFE17 DTC enable register B
|
||||
DTCERC 0xFFFE18 DTC enable register C
|
||||
DTCERD 0xFFFE19 DTC enable register D
|
||||
DTCERE 0xFFFE1A DTC enable register E
|
||||
DTCERF 0xFFFE1B DTC enable register F
|
||||
DTVECR 0xFFFE1F DTC vector register
|
||||
|
||||
P1DDR 0xFFFE30 Port 1 data direction register
|
||||
P3DDR 0xFFFE32 Port 3 data direction register
|
||||
P7DDR 0xFFFE36 Port 7 data direction register
|
||||
PADDR 0xFFFE39 Port A data direction register
|
||||
PBDDR 0xFFFE3A Port B data direction register
|
||||
PCDDR 0xFFFE3B Port C data direction register
|
||||
PDDDR 0xFFFE3C Port D data direction register
|
||||
PEDDR 0xFFFE3D Port E data direction register
|
||||
PFDDR 0xFFFE3E Port F data direction register
|
||||
PGDDR 0xFFFE3F Port G data direction register
|
||||
PAPCR 0xFFFE40 Port A pull-up MOS control register
|
||||
PBPCR 0xFFFE41 Port B pull-up MOS control register
|
||||
PCPCR 0xFFFE42 Port C pull-up MOS control register
|
||||
PDPCR 0xFFFE43 Port D pull-up MOS control register
|
||||
PEPCR 0xFFFE44 Port E pull-up MOS control register
|
||||
P3ODR 0xFFFE46 Port 3 open drain control register
|
||||
PAODR 0xFFFE47 Port A open drain control register
|
||||
|
||||
TSTR 0xFFFEB0 Timer start register
|
||||
TSYR 0xFFFEB1 Timer synchro register
|
||||
|
||||
IPRA 0xFFFEC0 Interrupt priority register A
|
||||
IPRB 0xFFFEC1 Interrupt priority register B
|
||||
IPRC 0xFFFEC2 Interrupt priority register C
|
||||
IPRD 0xFFFEC3 Interrupt priority register D
|
||||
IPRE 0xFFFEC4 Interrupt priority register E
|
||||
IPRF 0xFFFEC5 Interrupt priority register F
|
||||
IPRG 0xFFFEC6 Interrupt priority register G
|
||||
IPRI 0xFFFEC8 Interrupt priority register I
|
||||
IPRJ 0xFFFEC9 Interrupt priority register J
|
||||
IPRK 0xFFFECA Interrupt priority register K
|
||||
IPRM 0xFFFECC Interrupt priority register M
|
||||
|
||||
ABWCR 0xFFFED0 Bus width control register
|
||||
ASTCR 0xFFFED1 Access state control register
|
||||
WCRH 0xFFFED2 Wait control register H
|
||||
WCRL 0xFFFED3 Wait control register L
|
||||
BCRH 0xFFFED4 Bus control register H
|
||||
BCRL 0xFFFED5 Bus control register L
|
||||
|
||||
RAMER 0xFFFEDB RAM emulation register
|
||||
|
||||
MAR0AH 0xFFFEE0 Memory address register 0A H
|
||||
MAR0AL 0xFFFEE2 Memory address register 0A L
|
||||
IOAR0A 0xFFFEE4 I/O address register 0A
|
||||
ETCR0A 0xFFFEE6 Transfer count register 0A
|
||||
MAR0BH 0xFFFEE8 Memory address register 0B H
|
||||
MAR0BL 0xFFFEEA Memory address register 0B L
|
||||
IOAR0B 0xFFFEEC I/O address register 0B
|
||||
ETCR0B 0xFFFEEE Transfer count register 0B
|
||||
MAR1AH 0xFFFEF0 Memory address register 1A H
|
||||
MAR1AL 0xFFFEF2 Memory address register 1A L
|
||||
IOAR1A 0xFFFEF4 I/O address register 1A
|
||||
ETCR1A 0xFFFEF6 Transfer count register 1A
|
||||
MAR1BH 0xFFFEF8 Memory address register 1BH
|
||||
MAR1BL 0xFFFEFA Memory address register 1BL
|
||||
IOAR1B 0xFFFEFC I/O address register 1B
|
||||
ETCR1B 0xFFFEFE Transfer count register 1B
|
||||
|
||||
P1DR 0xFFFF00 Port 1 data register
|
||||
P3DR 0xFFFF02 Port 3 data register
|
||||
P7DR 0xFFFF06 Port 7 data register
|
||||
PADR 0xFFFF09 Port A data register
|
||||
PBDR 0xFFFF0A Port B data register
|
||||
PCDR 0xFFFF0B Port C data register
|
||||
PDDR 0xFFFF0C Port D data register
|
||||
PEDR 0xFFFF0D Port E data register
|
||||
PFDR 0xFFFF0E Port F data register
|
||||
PGDR 0xFFFF0F Port G data register
|
||||
|
||||
TCR_0 0xFFFF10 Timer control register 0
|
||||
TMDR_0 0xFFFF11 Timer mode register 0
|
||||
TIORH_0 0xFFFF12 Timer I/O control register H_0
|
||||
TIORL_0 0xFFFF13 Timer I/O control register L_0
|
||||
TIER_0 0xFFFF14 Timer interrupt enable register 0
|
||||
TSR_0 0xFFFF15 Timer status register 0
|
||||
TCNT_0 0xFFFF16 Timer counter 0
|
||||
TGRA_0 0xFFFF18 Timer general register A 0
|
||||
|
||||
TGRB_0 0xFFFF1A Timer general register B_0
|
||||
TGRC_0 0xFFFF1C Timer general register C_0
|
||||
TGRD_0 0xFFFF1E Timer general register D_0
|
||||
|
||||
TCR_1 0xFFFF20 Timer control register 1
|
||||
TMDR_1 0xFFFF21 Timer mode register 1
|
||||
TIOR_1 0xFFFF22 Timer I/O control register 1
|
||||
TIER_1 0xFFFF24 Timer interrupt enable register 1
|
||||
TSR_1 0xFFFF25 Timer status register 1
|
||||
TCNT_1 0xFFFF26 Timer counter 1
|
||||
TGRA_1 0xFFFF28 Timer general register A_1
|
||||
TGRB_1 0xFFFF2A Timer general register B_1
|
||||
|
||||
TCR_2 0xFFFF30 Timer control register 2
|
||||
TMDR_2 0xFFFF31 Timer mode register 2
|
||||
TIOR_2 0xFFFF32 Timer I/O control register 2
|
||||
TIER_2 0xFFFF34 Timer interrupt enable register 2
|
||||
TSR_2 0xFFFF35 Timer status register 2
|
||||
TCNT_2 0xFFFF36 Timer counter 2
|
||||
TGRA_2 0xFFFF38 Timer general register A_2
|
||||
TGRB_2 0xFFFF3A Timer general register B_2
|
||||
|
||||
DMAWER 0xFFFF60 DMA write enable register
|
||||
DMACR0A 0xFFFF62 DMA control register 0A
|
||||
DMACR0B 0xFFFF63 DMA control register 0B
|
||||
DMACR1A 0xFFFF64 DMA control register 1A
|
||||
DMACR1B 0xFFFF65 DMA control register 1B
|
||||
DMABCR 0xFFFF66 DMA band control register
|
||||
|
||||
TCR_0 0xFFFF68 Timer control register 0
|
||||
TCR_1 0xFFFF69 Timer control register 1
|
||||
TCSR_0 0xFFFF6A Timer control/status register 0
|
||||
TCSR_1 0xFFFF6B Timer control/status register 1
|
||||
TCORA_0 0xFFFF6C Time constant register A0
|
||||
TCORA_1 0xFFFF6D Time constant register A1
|
||||
TCORB_0 0xFFFF6E Time constant register B0
|
||||
TCORB_1 0xFFFF6F Time constant register B1
|
||||
TCNT_0 0xFFFF70 Timer counter 0
|
||||
TCNT_1 0xFFFF71 Timer counter 1
|
||||
TCSR 0xFFFF74 Timer control/status register
|
||||
|
||||
SMR_0 0xFFFF78 Serial mode register 0
|
||||
BRR_0 0xFFFF79 Bit rate register 0
|
||||
SCR_0 0xFFFF7A Serial control register 0
|
||||
TDR_0 0xFFFF7B Transmit data register 0
|
||||
SSR_0 0xFFFF7C Serial status register 0
|
||||
RDR_0 0xFFFF7D Receive data register 0
|
||||
SCMR_0 0xFFFF7E Smart card mode register 0
|
||||
|
||||
SMR_1 0xFFFF80 Serial mode register 1
|
||||
BRR_1 0xFFFF81 Bit rate register 1
|
||||
SCR_1 0xFFFF82 Serial control register 1
|
||||
TDR_1 0xFFFF83 Transmit data register 1
|
||||
SSR_1 0xFFFF84 Serial status register 1
|
||||
RDR_1 0xFFFF85 Receive data register 1
|
||||
SCMR_1 0xFFFF86 Smart card mode register 1
|
||||
SMR_2 0xFFFF88 Serial mode register 2
|
||||
BRR_2 0xFFFF89 Bit rate register 2
|
||||
SCR_2 0xFFFF8A Serial control register 2
|
||||
TDR_2 0xFFFF8B Transmit data register 2
|
||||
SSR_2 0xFFFF8C Serial status register 2
|
||||
RDR_2 0xFFFF8D Receive data register 2
|
||||
SCMR_2 0xFFFF8E Smart card mode register 2
|
||||
|
||||
ADDRAH 0xFFFF90 A/D data register AH
|
||||
ADDRAL 0xFFFF91 A/D data register AL
|
||||
ADDRBH 0xFFFF92 A/D data register BH
|
||||
ADDRBL 0xFFFF93 A/D data register BL
|
||||
ADDRCH 0xFFFF94 A/D data register CH
|
||||
ADDRCL 0xFFFF95 A/D data register CL
|
||||
ADDRDH 0xFFFF96 A/D data register DH
|
||||
ADDRDL 0xFFFF97 A/D data register DL
|
||||
ADCSR 0xFFFF98 A/D control/status register
|
||||
ADCR 0xFFFF99 A/D control register
|
||||
|
||||
FLMCR1 0xFFFFA8 Flash memory control register 1
|
||||
FLMCR2 0xFFFFA9 Flash memory control register 2
|
||||
|
||||
EBR1 0xFFFFAA Erase block register 1
|
||||
EBR2 0xFFFFAB Erase block register 2
|
||||
|
||||
PORT1 0xFFFFB0 Port 1 register
|
||||
PORT3 0xFFFFB2 Port 3 register
|
||||
PORT4 0xFFFFB3 Port 4 register
|
||||
PORT7 0xFFFFB6 Port 7 register
|
||||
PORT9 0xFFFFB8 Port 9 register
|
||||
PORTA 0xFFFFB9 Port A register
|
||||
PORTB 0xFFFFBA Port B register
|
||||
PORTC 0xFFFFBB Port C register
|
||||
PORTD 0xFFFFBC Port D register
|
||||
PORTE 0xFFFFBD Port E register
|
||||
PORTF 0xFFFFBE Port F register
|
||||
PORTG 0xFFFFBF Port G register
|
||||
305
idasdk76/module/h8/h8.hpp
Normal file
305
idasdk76/module/h8/h8.hpp
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _H8_HPP
|
||||
#define _H8_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include "ins.hpp"
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
#define PROCMOD_NAME h8
|
||||
#define PROCMOD_NODE_NAME "$ h8"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// processor types
|
||||
|
||||
typedef uint16 proctype_t;
|
||||
|
||||
static const proctype_t none = 0;
|
||||
static const proctype_t P300 = 0x0001; // H8/300, H8/300H
|
||||
static const proctype_t P2000 = 0x0002; // H8S/2000
|
||||
static const proctype_t P2600 = 0x0004; // H8S/2600
|
||||
static const proctype_t PSX = 0x0008; // H8SX
|
||||
|
||||
// assume 'Normal mode' as the default
|
||||
static const proctype_t MODE_MASK= 0xF000;
|
||||
static const proctype_t MODE_MID = 0x1000; // H8SX
|
||||
static const proctype_t MODE_ADV = 0x2000; // H8/300H (!), H8S, H8SX
|
||||
static const proctype_t MODE_MAX = 0x3000; // H8SX
|
||||
|
||||
// submodel
|
||||
static const proctype_t SUBM_MASK= 0x0F00;
|
||||
static const proctype_t SUBM_TINY= 0x0100; // H8/300H Tiny model
|
||||
// full insn set and normal mode
|
||||
|
||||
static const proctype_t P30A = P300 | MODE_ADV;
|
||||
static const proctype_t P26A = P2600 | MODE_ADV;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#ifdef _MSC_VER
|
||||
#define ENUM8BIT : uint8
|
||||
#else
|
||||
#define ENUM8BIT
|
||||
#endif
|
||||
enum regnum_t ENUM8BIT
|
||||
{
|
||||
R0, R1, R2, R3, R4, R5, R6, R7, SP=R7,
|
||||
E0, E1, E2, E3, E4, E5, E6, E7,
|
||||
R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H,
|
||||
R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L,
|
||||
ER0, ER1, ER2, ER3, ER4, ER5, ER6, ER7,
|
||||
// don't change registers order above this line
|
||||
MACL, MACH,
|
||||
PC,
|
||||
CCR, EXR,
|
||||
rVcs, rVds, // virtual registers for code and data segments
|
||||
VBR, SBR, // base or segment registers
|
||||
};
|
||||
|
||||
//---------------------------------
|
||||
// Operand types:
|
||||
|
||||
/*
|
||||
o_reg 1 Register direct
|
||||
Rn
|
||||
x.reg
|
||||
o_phrase 2 Register indirect
|
||||
@ERn
|
||||
x.phrase contains register number
|
||||
x.phtype contains phrase type (normal, post, pre)
|
||||
o_displ 3 Register indirect with displacement
|
||||
@(d:2,ERn)/@(d:16,ERn)/@(d:32,ERn)
|
||||
x.reg, x.addr, disp_16, disp_32, disp_2
|
||||
o_displ 4 Index register indirect with displacement
|
||||
@(d:16, RnL.B)/@(d:16,Rn.W)/@(d:16,ERn.L)
|
||||
@(d:32, RnL.B)/@(d:32,Rn.W)/@(d:32,ERn.L)
|
||||
x.displtype = dt_regidx,
|
||||
x.reg,
|
||||
x.addr - disp_16, disp_32, idx_byte/word/long
|
||||
o_phrase 5 Register indirect with post-inc/pre-dec/pre-inc/post-dec
|
||||
@ERn+/@-ERn/@+ERn/@ERn-
|
||||
o_mem 6 Absolute address
|
||||
@aa:8/@aa:16/@aa:24/@aa:32
|
||||
x.memtype = @aa:8 ? mem_sbr : mem_direct
|
||||
x.addr
|
||||
o_imm 7 Immediate
|
||||
#x:2/#xx:3/#xx:4/#xx:5/#xx:8/#xx:16/#xx:32
|
||||
#1/#2/#4/#8/#16
|
||||
x.value
|
||||
o_near 8 Program-counter relative
|
||||
@(d:8,PC)/@(d:16,PC)
|
||||
o_pcidx 9 Program-counter relative with index register
|
||||
@(RnL.B,PC)/@(Rn.W,PC)/@(ERn.L,PC)
|
||||
x.reg
|
||||
o_mem 10 Memory indirect
|
||||
@@aa:8
|
||||
x.memtype = mem_ind
|
||||
x.addr
|
||||
o_mem 11 Extended memory indirect
|
||||
@@vec:7
|
||||
x.memtype = mem_vec7
|
||||
x.addr
|
||||
o_reglist Register list
|
||||
x.reg, x.nregs
|
||||
o_displ first operand of MOVA insn
|
||||
@(d16,<EA>.[BW])/@(d32:<EA>.[BW])
|
||||
x.displtype = dt_movaop1,
|
||||
x.addr,
|
||||
x.szfl - disp_16/disp_32/idx_byte/idx_word
|
||||
x.idxt - <EA> type
|
||||
<EA> type:
|
||||
o_reg - x.reg EQ to o_regidx
|
||||
o_phrase - x.phrase,x.idxdt
|
||||
o_displ - x.reg,x.value,x.idxsz,x.idxdt
|
||||
o_regidx - x.reg,x.value,x.idxsz,x.idxdt
|
||||
o_mem - x.value,x.idsz,x.idxdt
|
||||
*/
|
||||
|
||||
#define o_reglist o_idpspec0
|
||||
#define o_pcidx o_idpspec1
|
||||
|
||||
#define phtype specflag1 // phrase type:
|
||||
const int ph_normal = 0; // just simple indirection
|
||||
const int ph_pre_dec = 0x10; // -@Rn ^ 3 -> @Rn+
|
||||
const int ph_post_inc = 0x13; // @Rn+
|
||||
const int ph_pre_inc = 0x11; // +@ERn
|
||||
const int ph_post_dec = 0x12; // @ERn-
|
||||
|
||||
#define displtype specflag1 // displ type:
|
||||
const int dt_normal = 0; // Register indirect with displacement
|
||||
const int dt_regidx = 1; // Index register indirect with displacement
|
||||
const int dt_movaop1 = 2; // first operand of MOVA insn
|
||||
|
||||
#define szfl specflag2 // various operand size flags
|
||||
// index target
|
||||
const int idx_byte = 0x01; // .b
|
||||
const int idx_word = 0x02; // .w
|
||||
const int idx_long = 0x04; // .l
|
||||
// size of operand displ
|
||||
const int disp_16 = 0x10; // 16bit displacement
|
||||
const int disp_24 = 0x20; // 24bit displacement
|
||||
const int disp_32 = 0x40; // 32bit displacement
|
||||
const int disp_2 = 0x80; // 2bit displacement
|
||||
|
||||
#define memtype specflag1 // mem type:
|
||||
const int mem_direct = 0; // x.addr - direct memory ref
|
||||
const int mem_sbr = 1; // SBR based @aa:8
|
||||
const int mem_vec7 = 2; // @@vec:7
|
||||
const int mem_ind = 3; // @@aa:8
|
||||
|
||||
#define nregs specflag1 // o_reglist: number of registers
|
||||
|
||||
// MOVA Op1 store
|
||||
#define idxt specflag3 // MOVA: optype_t of index
|
||||
#define idxsz specflag4 // MOVA: size of index
|
||||
#define idxdt specval // MOVA: index phtype,displtype,memtype
|
||||
|
||||
//------------------------------------------------------------------
|
||||
const uint16 aux_none = 0; // no postfix
|
||||
const uint16 aux_byte = 1; // .b postfix
|
||||
const uint16 aux_word = 2; // .w postfix
|
||||
const uint16 aux_long = 3; // .l postfix
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define UAS_HEW 0x0001 // HEW assembler
|
||||
|
||||
//------------------------------------------------------------------
|
||||
ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea
|
||||
ea_t calc_mem_sbr_based(const insn_t &insn, ea_t ea); // map virtual @aa:8 physical ea
|
||||
|
||||
void idaapi h8_segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
int idaapi h8_is_align_insn(ea_t ea);
|
||||
bool idaapi create_func_frame(func_t *pfn);
|
||||
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
|
||||
bool idaapi is_return_insn(const insn_t &insn);
|
||||
|
||||
int is_jump_func(const func_t *pfn, ea_t *jump_target);
|
||||
int may_be_func(const insn_t &insn); // can a function start here?
|
||||
int is_sane_insn(const insn_t &insn, int nocrefs);
|
||||
bool idaapi h8_is_switch(switch_info_t *si, const insn_t &insn);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct h8_iohandler_t : public iohandler_t
|
||||
{
|
||||
h8_iohandler_t(netnode &nn) : iohandler_t(nn) {}
|
||||
virtual void get_cfg_filename(char *buf, size_t bufsize) override;
|
||||
};
|
||||
|
||||
struct h8_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
h8_iohandler_t ioh = h8_iohandler_t(helper);
|
||||
proctype_t ptype = none; // contains all bits which correspond
|
||||
// to the supported processors set
|
||||
char show_sizer = -1;
|
||||
uchar code = 0;
|
||||
uchar code3 = 0;
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
inline bool advanced(void) { return (ptype & MODE_MASK) != 0; }
|
||||
inline bool is_h8s(void) { return (ptype & (P2000|P2600)) != 0; }
|
||||
inline bool is_h8sx(void) { return (ptype & PSX) != 0; }
|
||||
inline bool is_tiny(void) { return (ptype & SUBM_TINY) != 0; }
|
||||
|
||||
inline regnum_t r0(void) { return advanced() ? ER0 : R0; }
|
||||
|
||||
inline bool is_hew_asm(void) const
|
||||
{
|
||||
return (ash.uflag & UAS_HEW) != 0;
|
||||
}
|
||||
|
||||
void load_symbols(void);
|
||||
const char *find_sym(ea_t address);
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/);
|
||||
void set_cpu(int cpuno);
|
||||
int get_displ_outf(const op_t &x, flags_t F);
|
||||
ea_t trim_ea_branch(ea_t ea) const; // trim address according to proc mode
|
||||
void h8_header(outctx_t &ctx);
|
||||
void trimaddr(op_t &x);
|
||||
void opatHL(op_t &x, op_dtype_t dtyp);
|
||||
void opdsp16(insn_t &insn, op_t &x, op_dtype_t dtyp);
|
||||
void opdsp32(insn_t &insn, op_t &x, op_dtype_t dtyp);
|
||||
bool read_operand(insn_t &insn, op_t &x, ushort flags);
|
||||
bool map014(insn_t &insn);
|
||||
bool map4(insn_t &insn);
|
||||
int ana(insn_t *pinsn);
|
||||
int exit_40(insn_t &insn);
|
||||
int exit_54_56(insn_t &insn, uint8 rts, uint8 rtsl);
|
||||
int exit_59_5D(insn_t &insn, uint16 jump, uint16 branch);
|
||||
int exit_7B(insn_t &insn);
|
||||
int h8sx_03(insn_t &insn);
|
||||
int h8sx_0A(insn_t &insn);
|
||||
int h8sx_1A(insn_t &insn);
|
||||
int h8sx_6A(insn_t &insn);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload);
|
||||
int h8sx_6B(insn_t &insn);
|
||||
int h8sx_78(insn_t &insn);
|
||||
int h8sx_79(insn_t &insn);
|
||||
int h8sx_7A(insn_t &insn);
|
||||
bool h8sx_010D(insn_t &insn);
|
||||
bool h8sx_010E(insn_t &insn);
|
||||
bool insn_ldc(insn_t &insn, uint8 byte2, regnum_t reg);
|
||||
bool h8sx_01_exr(insn_t &insn);
|
||||
bool insn_mova(insn_t &insn);
|
||||
int insn_mova_reg(insn_t &insn, uint8 opcode, uint8 rs, bool is_reg_equal);
|
||||
bool h8sx_01_other(insn_t &insn);
|
||||
bool insn_addx_imm(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, bool check_byte3);
|
||||
bool insn_bra(insn_t &insn, uint8 byte2, uint8 byte3);
|
||||
bool insn_bfld_bfst(insn_t &insn, uint8 byte2, uint8 byte3, bool is_bfld);
|
||||
bool use_leaf_map(insn_t &insn, const struct map_t *m, uint8 idx);
|
||||
bool op_from_byte(insn_t &insn, op_t &x, uint8 byte2);
|
||||
bool read_1st_op(insn_t &insn, uint8 byte2, uint8 byte3_hiNi);
|
||||
bool op_phrase(const insn_t &insn, op_t &x, uint8 reg, int pht, op_dtype_t dtype=dt_byte);
|
||||
bool op_displ_regidx(insn_t &insn, op_t &x, uint8 selector, bool is_32, uint8 reg);
|
||||
int emu(const insn_t &insn);
|
||||
int h8_get_frame_retsize(const func_t *);
|
||||
int h8sx_7C(insn_t &insn);
|
||||
int h8sx_7D(insn_t &insn);
|
||||
bool h8sx_010_01dd(insn_t &insn, uint16 postfix);
|
||||
bool h8sx_ldm(insn_t &insn);
|
||||
bool insn_mac(insn_t &insn);
|
||||
bool insn_tas(insn_t &insn);
|
||||
bool op_phrase_prepost(const insn_t &insn, op_t &x, uint8 reg, uint8 selector);
|
||||
bool op_phrase_displ2(const insn_t &insn, op_t &x, uint8 reg, uint8 displ);
|
||||
int h8sx_01(insn_t &insn);
|
||||
bool h8sx_010_00dd(insn_t &insn);
|
||||
int h8sx_7E(insn_t &insn);
|
||||
int h8sx_7F(insn_t &insn);
|
||||
int unpack_8bit_shift(const map_t *m, insn_t &insn, uint16 itype, uint16 itype2);
|
||||
int h8sx_10(insn_t &insn);
|
||||
int h8sx_11(insn_t &insn);
|
||||
bool h8sx_0108(insn_t &insn);
|
||||
bool h8sx_0109_010A(insn_t &insn,op_t ®op, op_t &genop);
|
||||
int h8sx_0F(insn_t &insn);
|
||||
int h8sx_1F(insn_t &insn);
|
||||
void add_code_xref(const insn_t &insn, const op_t &x, ea_t ea);
|
||||
|
||||
void h8_assumes(outctx_t &ctx);
|
||||
void trace_sp(const insn_t &insn) const;
|
||||
bool get_op_value(uval_t *value, const insn_t &_insn, const op_t &x) const;
|
||||
bool spoils(const insn_t &insn, int reg) const;
|
||||
void check_base_reg_change_value(const insn_t &insn) const;
|
||||
void h8_segstart(outctx_t &ctx, segment_t *Srange) const;
|
||||
void h8_gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const;
|
||||
void h8_footer(outctx_t &ctx) const;
|
||||
|
||||
void load_from_idb();
|
||||
};
|
||||
extern int data_id;
|
||||
|
||||
#endif // _H8_HPP
|
||||
134
idasdk76/module/h8/ins.cpp
Normal file
134
idasdk76/module/h8/ins.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "h8.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
{ "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add binary
|
||||
{ "adds", CF_USE1|CF_USE2|CF_CHG2 }, // Add with sign extension
|
||||
{ "addx", CF_USE1|CF_USE2|CF_CHG2 }, // Add with extend carry
|
||||
{ "and", CF_USE1|CF_USE2|CF_CHG2 }, // Logical AND
|
||||
{ "andc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical AND with control register
|
||||
{ "band", CF_USE1|CF_USE2|CF_CHG2 }, // Bit AND
|
||||
{ "bra", CF_USE1|CF_STOP|CF_JUMP }, // Branch always
|
||||
{ "brn", CF_USE1 }, // Branch never
|
||||
{ "bhi", CF_USE1 }, // Branch if higher
|
||||
{ "bls", CF_USE1 }, // Branch if lower or same
|
||||
{ "bcc", CF_USE1 }, // Branch if carry clear (higher or same)
|
||||
{ "bcs", CF_USE1 }, // Branch if carry set (lower)
|
||||
{ "bne", CF_USE1 }, // Branch if not equal
|
||||
{ "beq", CF_USE1 }, // Branch if equal
|
||||
{ "bvc", CF_USE1 }, // Branch if overflow clear
|
||||
{ "bvs", CF_USE1 }, // Branch if overflow set
|
||||
{ "bpl", CF_USE1 }, // Branch if plus
|
||||
{ "bmi", CF_USE1 }, // Branch if minus
|
||||
{ "bge", CF_USE1 }, // Branch if greates or equal
|
||||
{ "blt", CF_USE1 }, // Branch if less
|
||||
{ "bgt", CF_USE1 }, // Branch if greater
|
||||
{ "ble", CF_USE1 }, // Branch if less or equal
|
||||
{ "bclr", CF_USE1|CF_USE2|CF_CHG2 }, // Bit clear
|
||||
{ "biand", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert AND
|
||||
{ "bild", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert load
|
||||
{ "bior", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert OR
|
||||
{ "bist", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert store
|
||||
{ "bixor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit invert XOR
|
||||
{ "bld", CF_USE1|CF_USE2 }, // Bit load
|
||||
{ "bnot", CF_USE1|CF_USE2|CF_CHG2 }, // Bit NOT
|
||||
{ "bor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit OR
|
||||
{ "bset", CF_USE1|CF_USE2|CF_CHG2 }, // Bit set
|
||||
{ "bsr", CF_USE1|CF_CALL }, // Branch to subroutine
|
||||
{ "bst", CF_USE1|CF_USE2|CF_CHG2 }, // Bit store
|
||||
{ "btst", CF_USE1|CF_USE2 }, // Bit test
|
||||
{ "bxor", CF_USE1|CF_USE2|CF_CHG2 }, // Bit XOR
|
||||
{ "clrmac", 0 }, // Clear MAC register
|
||||
{ "cmp", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "daa", CF_USE1|CF_CHG1 }, // Decimal adjust add
|
||||
{ "das", CF_USE1|CF_CHG1 }, // Decimal adjust subtract
|
||||
{ "dec", CF_USE1|CF_USE2|CF_CHG2 }, // Decrement
|
||||
{ "divxs", CF_USE1|CF_USE2|CF_CHG2 }, // Divide extended as signed
|
||||
{ "divxu", CF_USE1|CF_USE2|CF_CHG2 }, // Divide extended as unsigned
|
||||
{ "eepmov", 0 }, // Move data to EEPROM
|
||||
{ "exts", CF_USE1|CF_USE2|CF_CHG2 }, // Extend as signed
|
||||
{ "extu", CF_USE1|CF_USE2|CF_CHG2 }, // Extend as unsigned
|
||||
{ "inc", CF_USE1|CF_USE2|CF_CHG2 }, // Increment
|
||||
{ "jmp", CF_USE1|CF_STOP|CF_JUMP }, // Jump
|
||||
{ "jsr", CF_USE1|CF_CALL }, // Jump to subroutine
|
||||
{ "ldc", CF_USE1|CF_CHG2 }, // Load to control register
|
||||
{ "ldm", CF_USE1|CF_CHG2 }, // Load to multiple registers
|
||||
{ "ldmac", CF_USE1|CF_CHG2 }, // Load to MAC register
|
||||
{ "mac", CF_USE1|CF_USE2 }, // Multiply and accumulate
|
||||
{ "mov", CF_USE1|CF_CHG2 }, // Move data
|
||||
{ "movfpe", CF_USE1|CF_CHG2 }, // Move from peripheral with E clock
|
||||
{ "movtpe", CF_USE1|CF_CHG2 }, // Move to peripheral with E clock
|
||||
{ "mulxs", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply extend as signed
|
||||
{ "mulxu", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply extend as unsigned
|
||||
{ "neg", CF_USE1|CF_CHG1 }, // Negate
|
||||
{ "nop", 0 }, // No operation
|
||||
{ "not", CF_USE1|CF_CHG1 }, // Logical complement
|
||||
{ "or", CF_USE1|CF_USE2|CF_CHG2 }, // Logical OR
|
||||
{ "orc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical OR with control register
|
||||
{ "pop", CF_CHG1 }, // Pop data from stack
|
||||
{ "push", CF_USE1 }, // Push data on stack
|
||||
{ "rotl", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate left
|
||||
{ "rotr", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate right
|
||||
{ "rotxl", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate with extend carry left
|
||||
{ "rotxr", CF_USE1|CF_USE2|CF_CHG2 }, // Rotate with extend carry right
|
||||
{ "rte", CF_STOP }, // Return from exception
|
||||
{ "rts", CF_STOP }, // Return from subroutine
|
||||
{ "shal", CF_USE1|CF_USE2|CF_CHG2 }, // Shift arithmetic left
|
||||
{ "shar", CF_USE1|CF_USE2|CF_CHG2 }, // Shift arithmetic right
|
||||
{ "shll", CF_USE1|CF_USE2|CF_CHG2 }, // Shift logical left
|
||||
{ "shlr", CF_USE1|CF_USE2|CF_CHG2 }, // Shift logical right
|
||||
{ "sleep", 0 }, // Power down mode
|
||||
{ "stc", CF_USE1|CF_CHG2 }, // Store from control register
|
||||
{ "stm", CF_USE1|CF_CHG2 }, // Store from multiple registers
|
||||
{ "stmac", CF_USE1|CF_CHG2 }, // Store from MAC register
|
||||
{ "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract binary
|
||||
{ "subs", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract with sign extension
|
||||
{ "subx", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract with extend carry
|
||||
{ "tas", CF_USE1|CF_CHG1 }, // Test and set
|
||||
{ "trapa", CF_USE1|CF_CALL }, // Trap always
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Logical XOR
|
||||
{ "xorc", CF_USE1|CF_USE2|CF_CHG2 }, // Logical XOR with control register
|
||||
|
||||
// H8SX
|
||||
{ "rte/l", CF_STOP|CF_USE1|CF_CHG1 }, // Returns from an exception,
|
||||
// restoring data to multiple general registers
|
||||
{ "rts/l", CF_STOP|CF_USE1|CF_CHG1 }, // Returns from a subroutine,
|
||||
// restoring data to multiple general registers
|
||||
{ "movmd", 0 }, // Transfers a data block
|
||||
{ "movsd", CF_USE1 }, // Transfers a data block with zero detection
|
||||
{ "bra/s", CF_USE1|CF_STOP }, // Branch always after the next instruction (delay slot)
|
||||
{ "mova/b", CF_USE1|CF_CHG2 }, // MOVe effective Address/B
|
||||
{ "mova/w", CF_USE1|CF_CHG2 }, // MOVe effective Address/W
|
||||
{ "mova/l", CF_USE1|CF_CHG2 }, // MOVe effective Address/L
|
||||
{ "bset/ne", CF_USE1|CF_USE2|CF_CHG2 }, // Bit SET if Not Equal
|
||||
{ "bset/eq", CF_USE1|CF_USE2|CF_CHG2 }, // Bit SET if EQual
|
||||
{ "bclr/ne", CF_USE1|CF_USE2|CF_CHG2 }, // Bit CLeaR if Not Equal
|
||||
{ "bclr/eq", CF_USE1|CF_USE2|CF_CHG2 }, // Bit CLear if EQual
|
||||
{ "bstz", CF_USE1|CF_USE2|CF_CHG2 }, // Bit STore Zero flag
|
||||
{ "bistz", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Invert STore Zero flag
|
||||
{ "bfld", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Bit Field LoaD
|
||||
{ "bfst", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Bit Field STore
|
||||
{ "muls", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Signed
|
||||
{ "divs", CF_USE1|CF_USE2|CF_CHG2 }, // DIVide as Signed
|
||||
{ "mulu", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Unsigned
|
||||
{ "divu", CF_USE1|CF_USE2|CF_CHG2 }, // DIVide as Unsigned
|
||||
{ "muls/u", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Signed
|
||||
{ "mulu/u", CF_USE1|CF_USE2|CF_CHG2 }, // MULtiply as Unsigned
|
||||
{ "bra/bc", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // BRAnch if Bit Cleared
|
||||
{ "bra/bs", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // BRAnch if Bit Set
|
||||
{ "bsr/bc", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to SubRoutine if Bit Cleared
|
||||
{ "bsr/bs", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to SubRoutine if Bit Set
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == H8_last);
|
||||
137
idasdk76/module/h8/ins.hpp
Normal file
137
idasdk76/module/h8/ins.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
|
||||
H8_null = 0, // Unknown Operation
|
||||
|
||||
H8_add, // Add binary
|
||||
H8_adds, // Add with sign extension
|
||||
H8_addx, // Add with extend carry
|
||||
H8_and, // Logical AND
|
||||
H8_andc, // Logical AND with control register
|
||||
H8_band, // Bit AND
|
||||
H8_bra, // Branch always
|
||||
H8_brn, // Branch never
|
||||
H8_bhi, // Branch if higher
|
||||
H8_bls, // Branch if lower or same
|
||||
H8_bcc, // Branch if carry clear (higher or same)
|
||||
H8_bcs, // Branch if carry set (lower)
|
||||
H8_bne, // Branch if not equal
|
||||
H8_beq, // Branch if equal
|
||||
H8_bvc, // Branch if overflow clear
|
||||
H8_bvs, // Branch if overflow set
|
||||
H8_bpl, // Branch if plus
|
||||
H8_bmi, // Branch if minus
|
||||
H8_bge, // Branch if greates or equal
|
||||
H8_blt, // Branch if less
|
||||
H8_bgt, // Branch if greater
|
||||
H8_ble, // Branch if less or equal
|
||||
H8_bclr, // Bit clear
|
||||
H8_biand, // Bit invert AND
|
||||
H8_bild, // Bit invert load
|
||||
H8_bior, // Bit invert OR
|
||||
H8_bist, // Bit invert store
|
||||
H8_bixor, // Bit invert XOR
|
||||
H8_bld, // Bit load
|
||||
H8_bnot, // Bit NOT
|
||||
H8_bor, // Bit OR
|
||||
H8_bset, // Bit set
|
||||
H8_bsr, // Branch to subroutine
|
||||
H8_bst, // Bit store
|
||||
H8_btst, // Bit test
|
||||
H8_bxor, // Bit XOR
|
||||
H8_clrmac, // Clear MAC register
|
||||
H8_cmp, // Compare
|
||||
H8_daa, // Decimal adjust add
|
||||
H8_das, // Decimal adjust subtract
|
||||
H8_dec, // Decrement
|
||||
H8_divxs, // Divide extended as signed
|
||||
H8_divxu, // Divide extended as unsigned
|
||||
H8_eepmov, // Move data to EEPROM
|
||||
H8_exts, // Extend as signed
|
||||
H8_extu, // Extend as unsigned
|
||||
H8_inc, // Increment
|
||||
H8_jmp, // Jump
|
||||
H8_jsr, // Jump to subroutine
|
||||
H8_ldc, // Load to control register
|
||||
H8_ldm, // Load to multiple registers
|
||||
H8_ldmac, // Load to MAC register
|
||||
H8_mac, // Multiply and accumulate
|
||||
H8_mov, // Move data
|
||||
H8_movfpe, // Move from peripheral with E clock
|
||||
H8_movtpe, // Move to peripheral with E clock
|
||||
H8_mulxs, // Multiply extend as signed
|
||||
H8_mulxu, // Multiply extend as unsigned
|
||||
H8_neg, // Negate
|
||||
H8_nop, // No operation
|
||||
H8_not, // Logical complement
|
||||
H8_or, // Logical OR
|
||||
H8_orc, // Logical OR with control register
|
||||
H8_pop, // Pop data from stack
|
||||
H8_push, // Push data on stack
|
||||
H8_rotl, // Rotate left
|
||||
H8_rotr, // Rotate right
|
||||
H8_rotxl, // Rotate with extend carry left
|
||||
H8_rotxr, // Rotate with extend carry right
|
||||
H8_rte, // Return from exception
|
||||
H8_rts, // Return from subroutine
|
||||
H8_shal, // Shift arithmetic left
|
||||
H8_shar, // Shift arithmetic right
|
||||
H8_shll, // Shift logical left
|
||||
H8_shlr, // Shift logical right
|
||||
H8_sleep, // Power down mode
|
||||
H8_stc, // Store from control register
|
||||
H8_stm, // Store from multiple registers
|
||||
H8_stmac, // Store from MAC register
|
||||
H8_sub, // Subtract binary
|
||||
H8_subs, // Subtract with sign extension
|
||||
H8_subx, // Subtract with extend carry
|
||||
H8_tas, // Test and set
|
||||
H8_trapa, // Trap always
|
||||
H8_xor, // Logical XOR
|
||||
H8_xorc, // Logical XOR with control register
|
||||
|
||||
// H8SX
|
||||
H8_rtel, // Returns from an exception, restoring data to multiple general registers
|
||||
H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers
|
||||
H8_movmd, // Transfers a data block
|
||||
H8_movsd, // Transfers a data block with zero detection
|
||||
H8_bras, // Branch always after the next instruction (delay slot)
|
||||
H8_movab, // MOVe effective Address/B
|
||||
H8_movaw, // MOVe effective Address/W
|
||||
H8_moval, // MOVe effective Address/L
|
||||
H8_bsetne, // Bit SET if Not Equal
|
||||
H8_bseteq, // Bit SET if EQual
|
||||
H8_bclrne, // Bit CLeaR if Not Equal
|
||||
H8_bclreq, // Bit CLeaR if Equal
|
||||
H8_bstz, // Bit STore Zero flag
|
||||
H8_bistz, // Bit Invert STore Zero flag
|
||||
H8_bfld, // Bit Field LoaD
|
||||
H8_bfst, // Bit Field STore
|
||||
H8_muls, // MULtiply as Signed
|
||||
H8_divs, // DIVide as Signed
|
||||
H8_mulu, // MULtiply as Unsigned
|
||||
H8_divu, // DIVide as Unsigned
|
||||
H8_mulsu, // MULtiply as Signed
|
||||
H8_muluu, // MULtiply as Unsigned
|
||||
H8_brabc, // BRAnch if Bit Cleared
|
||||
H8_brabs, // BRAnch if Bit Set
|
||||
H8_bsrbc, // Branch to SubRoutine if Bit Cleared
|
||||
H8_bsrbs, // Branch to SubRoutine if Bit Set
|
||||
|
||||
H8_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
57
idasdk76/module/h8/makefile
Normal file
57
idasdk76/module/h8/makefile
Normal file
@@ -0,0 +1,57 @@
|
||||
PROC=h8
|
||||
CONFIGS=h8.cfg
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ana.cpp h8.hpp ins.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)jumptable.hpp \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \
|
||||
$(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp emu.cpp h8.hpp ins.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
h8.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp h8.hpp ins.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp h8.hpp ins.hpp reg.cpp
|
||||
416
idasdk76/module/h8/out.cpp
Normal file
416
idasdk76/module/h8/out.cpp
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "h8.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <struct.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_h8_t : public outctx_t
|
||||
{
|
||||
out_h8_t(void) = delete; // not used
|
||||
public:
|
||||
void outreg(int r) { out_register(ph.reg_names[r]); }
|
||||
void out_bad_address(ea_t addr);
|
||||
void out_sizer(char szfl);
|
||||
|
||||
void attach_name_comment(const op_t &x, ea_t v) const; // modifies idb!
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
};
|
||||
CASSERT(sizeof(out_h8_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_h8_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int h8_t::get_displ_outf(const op_t &x, flags_t F)
|
||||
{
|
||||
return OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED
|
||||
| ((is_stkvar(F, x.n) || (x.szfl & disp_32) || advanced()) ? OOFW_32 : OOFW_16);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8_t::out_bad_address(ea_t addr)
|
||||
{
|
||||
h8_t &pm = *static_cast<h8_t *>(procmod);
|
||||
const char *name = pm.find_sym(addr);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(addr, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t h8_t::trim_ea_branch(ea_t ea) const
|
||||
{
|
||||
switch ( ptype & MODE_MASK )
|
||||
{
|
||||
case MODE_MID:
|
||||
case MODE_ADV:
|
||||
return ea & 0x00FFFFFF;
|
||||
case MODE_MAX:
|
||||
return ea;
|
||||
}
|
||||
return ea & 0x0000FFFF;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_mem(const insn_t &insn, ea_t ea)
|
||||
{
|
||||
return to_ea(insn.cs, ea);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_mem_sbr_based(const insn_t &insn, ea_t ea)
|
||||
{
|
||||
sel_t base = get_sreg(insn.ea, SBR);
|
||||
return (base & 0xFFFFFF00) | (ea & 0x000000FF);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8_t::out_sizer(char szfl)
|
||||
{
|
||||
h8_t &pm = *static_cast<h8_t *>(procmod);
|
||||
if ( pm.show_sizer == -1 )
|
||||
pm.show_sizer = !qgetenv("H8_NOSIZER");
|
||||
if ( !pm.show_sizer )
|
||||
return;
|
||||
|
||||
if ( szfl & disp_2 )
|
||||
return;
|
||||
int size = (szfl & disp_32) ? 32 :
|
||||
(szfl & disp_24) ? 24 :
|
||||
(szfl & disp_16) ? 16 : 8;
|
||||
out_symbol(':');
|
||||
out_long(size, 10);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8_t::attach_name_comment(const op_t &x, ea_t v) const
|
||||
{
|
||||
if ( !has_cmt(F) )
|
||||
{
|
||||
qstring qbuf;
|
||||
if ( get_name_expr(&qbuf, insn.ea, x.n, v, BADADDR) > 0 )
|
||||
set_cmt(insn.ea, qbuf.begin(), false);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ea_t get_data_ref(ea_t ea)
|
||||
{
|
||||
ea_t to = BADADDR;
|
||||
xrefblk_t xb;
|
||||
for ( bool ok=xb.first_from(ea, XREF_DATA); ok; ok=xb.next_from() )
|
||||
{
|
||||
if ( xb.type == dr_O )
|
||||
return xb.to;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_h8_t::out_operand(const op_t &x)
|
||||
{
|
||||
h8_t &pm = *static_cast<h8_t *>(procmod);
|
||||
switch ( x.type )
|
||||
{
|
||||
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_reg:
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
case o_reglist:
|
||||
if ( pm.is_hew_asm() )
|
||||
out_symbol('(');
|
||||
outreg(x.reg);
|
||||
out_symbol('-');
|
||||
outreg(x.reg+x.nregs-1);
|
||||
if ( pm.is_hew_asm() )
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
out_symbol('#');
|
||||
out_value(x, OOFS_IFSIGN|OOFW_IMM);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
out_symbol('@');
|
||||
if ( x.memtype == mem_vec7 || x.memtype == mem_ind )
|
||||
out_symbol('@');
|
||||
// no break
|
||||
case o_near:
|
||||
{
|
||||
ea_t ea = x.memtype == mem_sbr
|
||||
? calc_mem_sbr_based(insn, x.addr)
|
||||
: calc_mem(insn, x.addr);
|
||||
if ( pm.is_hew_asm() && (x.szfl & disp_24) )
|
||||
out_symbol('@');
|
||||
out_addr_tag(ea);
|
||||
if ( x.memtype == mem_sbr
|
||||
|| !out_name_expr(x, ea, x.addr) )
|
||||
{
|
||||
out_bad_address(x.addr);
|
||||
if ( x.memtype == mem_sbr )
|
||||
attach_name_comment(x, ea);
|
||||
}
|
||||
if ( x.memtype != mem_vec7 )
|
||||
out_sizer(x.szfl);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
out_symbol('@');
|
||||
|
||||
if ( x.phtype == ph_pre_dec )
|
||||
out_symbol('-');
|
||||
else if ( x.phtype == ph_pre_inc )
|
||||
out_symbol('+');
|
||||
|
||||
outreg(x.phrase);
|
||||
|
||||
if ( x.phtype == ph_post_inc )
|
||||
out_symbol('+');
|
||||
else if ( x.phtype == ph_post_dec )
|
||||
out_symbol('-');
|
||||
|
||||
{
|
||||
ea_t ea = get_data_ref(insn.ea);
|
||||
if ( ea != BADADDR )
|
||||
attach_name_comment(x, ea);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
out_symbol('@');
|
||||
out_symbol('(');
|
||||
{
|
||||
int outf = pm.get_displ_outf(x, F);
|
||||
out_value(x, outf);
|
||||
out_sizer(x.szfl);
|
||||
}
|
||||
out_symbol(',');
|
||||
if ( x.displtype == dt_movaop1 )
|
||||
{
|
||||
op_t ea;
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.offb = insn.Op1.offo;
|
||||
ea.type = insn.Op1.idxt;
|
||||
ea.phrase = insn.Op1.phrase;
|
||||
ea.phtype = insn.Op1.idxdt;
|
||||
ea.addr = insn.Op1.value;
|
||||
ea.szfl = insn.Op1.idxsz;
|
||||
out_operand(ea);
|
||||
out_symbol('.');
|
||||
out_symbol(x.szfl & idx_byte ? 'b' :
|
||||
x.szfl & idx_word ? 'w' : 'l');
|
||||
}
|
||||
else if ( x.displtype == dt_regidx )
|
||||
{
|
||||
outreg(x.reg);
|
||||
out_symbol('.');
|
||||
out_symbol(x.szfl & idx_byte ? 'b' :
|
||||
x.szfl & idx_word ? 'w' : 'l');
|
||||
}
|
||||
else
|
||||
{
|
||||
outreg(x.reg);
|
||||
}
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
case o_pcidx:
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10096);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8_t::out_proc_mnem(void)
|
||||
{
|
||||
static const char *const postfixes[] = { NULL, ".b", ".w", ".l" };
|
||||
const char *postfix = postfixes[insn.auxpref];
|
||||
out_mnem(8, postfix);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
bool showOp1 = insn.Op1.shown();
|
||||
if ( showOp1 )
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
if ( showOp1 )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
}
|
||||
out_one_operand(1);
|
||||
}
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Srange) could be made const
|
||||
void h8_t::h8_segstart(outctx_t &ctx, segment_t *Srange) const
|
||||
{
|
||||
const char *predefined[] =
|
||||
{
|
||||
".text", // Text section
|
||||
".rdata", // Read-only data section
|
||||
".data", // Data sections
|
||||
".lit8", // Data sections
|
||||
".lit4", // Data sections
|
||||
".sdata", // Small data section, addressed through register $gp
|
||||
".sbss", // Small bss section, addressed through register $gp
|
||||
};
|
||||
|
||||
if ( Srange == NULL || is_spec_segm(Srange->type) )
|
||||
return;
|
||||
|
||||
qstring sname;
|
||||
qstring sclas;
|
||||
get_segm_name(&sname, Srange);
|
||||
get_segm_class(&sclas, Srange);
|
||||
|
||||
if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) )
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT),
|
||||
sclas == "CODE" ? ".text" : ".data",
|
||||
ash.cmnt,
|
||||
sname.c_str());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi h8_segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
void h8_t::h8_assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL )
|
||||
return;
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
|
||||
for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; i++ )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg || i == ph.reg_data_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
bool show = sra.start_ea == ea;
|
||||
if ( show )
|
||||
{
|
||||
sreg_range_t prev_sra;
|
||||
if ( get_prev_sreg_range(&prev_sra, ea, i) )
|
||||
show = sra.val != prev_sra.val;
|
||||
}
|
||||
if ( seg_started || show )
|
||||
ctx.gen_cmt_line("%-*s assume %s: %a", int(inf_get_indent()-strlen(ash.cmnt)-2), "", ph.reg_names[i], sra.val);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Generate stack variable definition line
|
||||
// If this function is NULL, then the kernel will create the line itself.
|
||||
void h8_t::h8_gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const
|
||||
{
|
||||
char sign = ' ';
|
||||
if ( v < 0 )
|
||||
{
|
||||
v = -v;
|
||||
sign = '-';
|
||||
}
|
||||
|
||||
char num[MAX_NUMBUF];
|
||||
btoa(num, sizeof(num), v);
|
||||
|
||||
qstring name = get_member_name(mptr->id);
|
||||
if ( is_hew_asm() )
|
||||
{
|
||||
ctx.out_printf(COLSTR("%s", SCOLOR_LOCNAME)
|
||||
COLSTR(": ", SCOLOR_SYMBOL)
|
||||
COLSTR(".assign", SCOLOR_ASMDIR)
|
||||
COLSTR(" %c", SCOLOR_SYMBOL)
|
||||
COLSTR("%s", SCOLOR_DNUM),
|
||||
name.c_str(), sign, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.out_printf(COLSTR("%-*s", SCOLOR_LOCNAME)
|
||||
COLSTR("= %c", SCOLOR_SYMBOL)
|
||||
COLSTR("%s", SCOLOR_DNUM),
|
||||
inf_get_indent(), name.c_str(), sign, num);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void h8_t::h8_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL);
|
||||
|
||||
if ( ptype == P300 )
|
||||
return;
|
||||
char procdir[MAXSTR];
|
||||
qsnprintf(procdir, MAXSTR, ".h8300%s%s",
|
||||
is_h8sx() ? "sx" : is_h8s() ? "s" : "h",
|
||||
advanced() ? "" : "n");
|
||||
ctx.gen_empty_line();
|
||||
ctx.gen_printf(DEFAULT_INDENT, "%s", procdir);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void h8_t::h8_footer(outctx_t &ctx) const
|
||||
{
|
||||
qstring nbuf = get_colored_name(inf_get_start_ea());
|
||||
const char *name = nbuf.c_str();
|
||||
const char *end = ash.end;
|
||||
if ( end == NULL )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name);
|
||||
else
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT),
|
||||
ash.end,
|
||||
ash.cmnt,
|
||||
name);
|
||||
}
|
||||
588
idasdk76/module/h8/reg.cpp
Normal file
588
idasdk76/module/h8/reg.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2001 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include "h8.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
#include <ieee.h>
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names[] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
|
||||
"r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
|
||||
"r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l",
|
||||
"er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
|
||||
"macl", "mach",
|
||||
"pc",
|
||||
"ccr", "exr",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"vbr", "sbr",
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names_sp_er7[] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp",
|
||||
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
|
||||
"r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
|
||||
"r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l",
|
||||
"er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
|
||||
"macl", "mach",
|
||||
"pc",
|
||||
"ccr", "exr",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"vbr", "sbr",
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names_r7_sp[] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
|
||||
"r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
|
||||
"r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l",
|
||||
"er0", "er1", "er2", "er3", "er4", "er5", "er6", "sp",
|
||||
"macl", "mach",
|
||||
"pc",
|
||||
"ccr", "exr",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"vbr", "sbr",
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar startcode_0[] = { 0x01, 0x00, 0x6D, 0xF3 }; // push.l er3
|
||||
static const uchar startcode_1[] = { 0x6D, 0xF3 }; // push.w r3
|
||||
|
||||
static const bytes_t startcodes[] =
|
||||
{
|
||||
{ sizeof(startcode_0), startcode_0 },
|
||||
{ sizeof(startcode_1), startcode_1 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// GNU ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gas =
|
||||
{
|
||||
AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP,
|
||||
0,
|
||||
"GNU assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
".org", // org
|
||||
NULL, // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'"', // char delimiter
|
||||
"\"", // special symbols in char and string constants
|
||||
|
||||
".ascii", // ascii string directive
|
||||
".byte", // byte directive
|
||||
".word", // word directive
|
||||
".long", // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
".double", // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".space %s", // uninited arrays
|
||||
"=", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
NULL, // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".globl", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".extern", // "extrn" name keyword
|
||||
// .extern directive requires an explicit object size
|
||||
".comm", // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof_fmt
|
||||
0, // flag2
|
||||
NULL, // cmnt2
|
||||
NULL, // low8
|
||||
NULL, // high8
|
||||
NULL, // low16
|
||||
NULL, // high16
|
||||
"#include \"%s\"", // a_include_fmt
|
||||
NULL, // a_vstruc_fmt
|
||||
NULL, // a_rva
|
||||
NULL, // a_yword
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// HEW ASM
|
||||
//-----------------------------------------------------------------------
|
||||
const asm_t hew =
|
||||
{
|
||||
AS_ASCIIC|AS_ALIGN2|ASH_HEXF1|ASD_DECF0|ASO_OCTF7|ASB_BINF4|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP,
|
||||
UAS_HEW,
|
||||
"HEW assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
".org", // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'"', // char delimiter
|
||||
"\"", // special symbols in char and string constants
|
||||
|
||||
".sdata", // ascii string directive
|
||||
".data.b", // byte directive
|
||||
".data.w", // word directive
|
||||
".data.l", // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
".double", // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".res %s", // uninited arrays
|
||||
": .assign", // equ that allows set/reset values
|
||||
//": .equ", // equ (does not allow for reuse)
|
||||
//": .reg (%s)",// equ for regs (does not allow for reuse)
|
||||
//": .bequ", // equ for bits (does not allow for reuse)
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".global", // "extrn" name keyword
|
||||
".comm", // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"~", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
"sizeof", // sizeof_fmt
|
||||
0, // flag2
|
||||
NULL, // cmnt2
|
||||
"low", // low8
|
||||
"high", // high8
|
||||
"lword", // low16
|
||||
"hword", // high16
|
||||
".include \"%s\"", // a_include_fmt
|
||||
NULL, // a_vstruc_fmt
|
||||
NULL, // a_rva
|
||||
NULL, // a_yword
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &gas, &hew, NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char cfgname[] = "h8.cfg";
|
||||
|
||||
void h8_iohandler_t::get_cfg_filename(char *buf, size_t bufsize)
|
||||
{
|
||||
qstrncpy(buf, cfgname, bufsize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *h8_t::find_sym(ea_t address)
|
||||
{
|
||||
const ioport_t *port = find_ioport(ioh.ports, address);
|
||||
return port ? port->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void h8_t::load_from_idb()
|
||||
{
|
||||
ioh.restore_device();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *h8_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/)
|
||||
{
|
||||
if ( keyword != NULL )
|
||||
return IDPOPT_BADKEY;
|
||||
if ( choose_ioport_device(&ioh.device, cfgname) )
|
||||
ioh.set_device_name(ioh.device.c_str(), IORESP_NONE);
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const proctype_t ptypes[] =
|
||||
{
|
||||
P300, // h8300
|
||||
P300 | MODE_ADV, // h8300a
|
||||
P300 | P2000 | P2600, // h8s300
|
||||
P300 | MODE_ADV | P2000 | P2600, // h8s300a
|
||||
P300 | P2000 | P2600 | PSX, // h8sxn
|
||||
P300 | MODE_MID | P2000 | P2600 | PSX, // h8sxm
|
||||
P300 | MODE_ADV | P2000 | P2600 | PSX, // h8sxa
|
||||
P300 | MODE_MAX | P2000 | P2600 | PSX, // h8sx
|
||||
P300 | MODE_ADV | SUBM_TINY, // h8368
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void h8_t::set_cpu(int cpuno)
|
||||
{
|
||||
ptype = ptypes[cpuno];
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
if ( advanced() && !is_tiny() )
|
||||
{
|
||||
ph.flag |= PR_DEFSEG32;
|
||||
}
|
||||
if ( is_h8sx() )
|
||||
{
|
||||
ph.flag |= PR_SEGS;
|
||||
ph.reg_last_sreg = SBR;
|
||||
ph.segreg_size = 4;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(SET_MODULE_DATA(h8_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi h8_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int ret = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
// __emit__(0xCC); // debugger trap
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
inf_set_be(true);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newasm: // new assembler type selected
|
||||
{
|
||||
int asmnum = va_arg(va, int);
|
||||
bool hew_asm = asmnum == 1;
|
||||
if ( advanced() )
|
||||
ph.reg_names = hew_asm ? register_names : register_names_r7_sp;
|
||||
else
|
||||
ph.reg_names = hew_asm ? register_names : register_names_sp_er7;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
if ( choose_ioport_device(&ioh.device, cfgname) )
|
||||
ioh.set_device_name(ioh.device.c_str(), IORESP_NONE);
|
||||
if ( is_h8sx() )
|
||||
{
|
||||
set_default_sreg_value(NULL, VBR, 0);
|
||||
set_default_sreg_value(NULL, SBR, 0xFFFFFF00);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
// restore ptype
|
||||
set_cpu(ph.get_proc_index());
|
||||
//fall through
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc: // new processor type
|
||||
set_cpu(va_arg(va, int));
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm: // new segment
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_jump_func:
|
||||
{
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
ea_t *jump_target = va_arg(va, ea_t *);
|
||||
ret = is_jump_func(pfn, jump_target);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_sane_insn:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
int no_crefs = va_arg(va, int);
|
||||
ret = is_sane_insn(insn, no_crefs) == 1 ? 1 : -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_may_be_func:
|
||||
// can a function start here?
|
||||
// arg: none, the instruction is in 'cmd'
|
||||
// returns: probability 0..100
|
||||
// 'cmd' structure is filled upon the entrace
|
||||
// the idp module is allowed to modify 'cmd'
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
ret = may_be_func(insn);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_gen_regvar_def:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
regvar_t *v = va_arg(va, regvar_t*);
|
||||
if ( is_hew_asm() )
|
||||
{
|
||||
ctx->gen_printf(0,
|
||||
COLSTR("%s", SCOLOR_REG)
|
||||
COLSTR(": .reg (", SCOLOR_SYMBOL)
|
||||
COLSTR("%s", SCOLOR_REG)
|
||||
COLSTR(")", SCOLOR_SYMBOL),
|
||||
v->user, v->canon);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_ret_insn:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
ret = is_return_insn(insn) ? 1 : -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_mnem:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_mnem(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
h8_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
h8_footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
h8_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segend:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
h8_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
h8_assumes(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_switch:
|
||||
{
|
||||
switch_info_t *si = va_arg(va, switch_info_t *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return h8_is_switch(si, *insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_sp_based:
|
||||
{
|
||||
int *mode = va_arg(va, int *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
*mode = is_sp_based(*insn, *op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
*frsize = h8_get_frame_retsize(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_gen_stkvar_def:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const member_t *mptr = va_arg(va, const member_t *);
|
||||
sval_t v = va_arg(va, sval_t);
|
||||
h8_gen_stkvar_def(*ctx, mptr, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_set_idp_options:
|
||||
{
|
||||
const char *keyword = va_arg(va, const char *);
|
||||
int value_type = va_arg(va, int);
|
||||
const char *value = va_arg(va, const char *);
|
||||
const char **errmsg = va_arg(va, const char **);
|
||||
bool idb_loaded = va_argi(va, bool);
|
||||
const char *retstr = set_idp_options(keyword, value_type, value, idb_loaded);
|
||||
if ( retstr == IDPOPT_OK )
|
||||
return 1;
|
||||
if ( errmsg != NULL )
|
||||
*errmsg = retstr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_align_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
return h8_is_align_insn(ea);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "Hitachi H8:"
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"h8300", "h8300a", "h8s300", "h8s300a",
|
||||
"h8sxn", "h8sxm", "h8sxa", "h8sx", "h8368", NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Hitachi H8/300H normal",
|
||||
"Hitachi H8/300H advanced",
|
||||
"Hitachi H8S normal",
|
||||
"Hitachi H8S advanced",
|
||||
"Hitachi H8SX normal",
|
||||
"Hitachi H8SX middle",
|
||||
"Hitachi H8SX advanced",
|
||||
"Hitachi H8SX maximum",
|
||||
"Renesas H8/3687 Group",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_H8, // id
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_USE32
|
||||
| PR_WORD_INS,
|
||||
// flag2
|
||||
PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names, // Register names
|
||||
qnumber(register_names), // Number of registers
|
||||
|
||||
rVcs, // first
|
||||
rVds, // last
|
||||
0, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
startcodes, // start sequences
|
||||
NULL, // see is_ret_insn callback in the notify() function
|
||||
|
||||
H8_null,
|
||||
H8_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size; -- doesn't exist
|
||||
{ 0, 7, 15, 0 }, // char real_width[4];
|
||||
// number of symbols after decimal point
|
||||
// 2byte float (0-does not exist)
|
||||
// normal float
|
||||
// normal double
|
||||
// long double
|
||||
H8_rts, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user