Ghidra: Help for Motorola 6809 EXG instruction

Created on 16 Mar 2019  路  5Comments  路  Source: NationalSecurityAgency/ghidra

I am currently defining a slaspec for the Motorola 6809 CPU.
I would need some help for the EXG instruction (It exchanges the contents of two registers).
A good documentation for EXG instruction You will find here: 6x09 Instruction Sets on page 66.

There are three challenges I can find no solution accepted by sleigh parser:

  • The two registers are defined in a separate data byte.
  • The two registers may have 8- or 16-bit which may not be mixed. If mixed => invalid instr.
  • There are "invalid" registers possible. If used => invalid instr.

Here my current approach:

# sleigh specification file for Motorola 6809
define endian=big;
define alignment=1;

define space RAM     type=ram_space      size=2  default;
define space register type=register_space size=1;

define register offset=0 size=1 [ A B DP ]; # 8-bit registers A, B, DP
define register offset=0 size=2 [ D ]; # 16-bit D reg. (Same addr. as A/B)
define register offset=8 size=1 [ CC ]; # 8-bit condition code register
define register offset=16 size=2 [ PC X Y U S ]; # 16-bit registers:

define token opbyte (8)
   op    = (0,7)
;

define token data8 (8)
    reg01= (4,7)                                                                
    reg02= (4,7)
    reg11= (0,3)
    reg12= (0,3)
;

# register set for EXG instruction 8-bit registers
attach variables [ reg01 ] [ _ _ _ _ _ _  _ _ A B CC DP _ _ _ _ ];
attach variables [ reg11 ] [ _ _ _ _ _ _  _ _ A B CC DP _ _ _ _ ];
# register set for EXG instruction 16-bit registers
attach variables [ reg02 ] [ D X Y U S PC _ _ _ _ _  _  _ _ _ _ ];
attach variables [ reg12 ] [ D X Y U S PC _ _ _ _ _  _  _ _ _ _ ];

# Exchange two 8-bit registers
# Test with registers A, B
:EXG reg01,reg11    is op=0x1E; (reg01=8 | reg01=9) & (reg11=8 | reg11=9)
{
    local tmp = reg01;
    reg01 = reg11;
    reg11 = tmp;
}

# Exchange two 16-bit registers
# Test with registers D, X
:EXG reg02,reg12    is op=0x1E; (reg02=0 | reg02=1) & (reg12=0 | reg12=1)
{
    local tmp = reg02;
    reg02 = reg12;
    reg12 = tmp;
}

Question

Most helpful comment

This should do what you want. Also for the 6309 which has a slightly different set of semantics. The approach is a little brute force and there are probably other clever ways, but this lays out all the subtle cases, and the cases when an operand is invalid which have specifically called out semantics.

Also note the GOTO semantics when the PC is one of the targets.

Looking forward to the full language!

# sleigh specification file for Motorola 6809
define endian=big;
define alignment=1;

define space RAM     type=ram_space      size=2  default;
define space register type=register_space size=1;

define register offset=0 size=1 [ A B DP ]; # 8-bit registers A, B, DP
define register offset=0 size=2 [ D ]; # 16-bit D reg. (Same addr. as A/B)
define register offset=8 size=1 [ CC ]; # 8-bit condition code register
define register offset=16 size=2 [ PC X Y U S ]; # 16-bit registers:

define register offset =32 size=2 [ exg16_r0           exg16_r1          ];
define register offset =32 size=1 [ exg8h_r0 exg8l_r0  exg8h_r1 exg8l_r1 ];
define token opbyte (8)
   op    = (0,7)
;

@define M6809 ""

define token data8 (8)
    reg01= (4,7)                                                                
    reg02= (4,7)
    reg11= (0,3)
    reg12= (0,3)
    reg0_exg = (4,7)
    reg1_exg = (0,3)
;

@ifdef M6309
EXG_r0Tmp: D    is reg0_exg=0 & D   { exg16_r0 = D; }
EXG_r0Tmp: X    is reg0_exg=1 & X   { exg16_r0 = X; }
EXG_r0Tmp: Y    is reg0_exg=2 & Y   { exg16_r0 = Y; }
EXG_r0Tmp: U    is reg0_exg=3 & U   { exg16_r0 = U; }
EXG_r0Tmp: S    is reg0_exg=4 & S   { exg16_r0 = S; }
EXG_r0Tmp: PC   is reg0_exg=5 & PC  { exg16_r0 = inst_next; }
EXG_r0Tmp: W    is reg0_exg=6 & W   { exg16_r0 = 0x0; }
EXG_r0Tmp: V    is reg0_exg=7 & V   { exg16_r0 = 0x0; }
EXG_r0Tmp: A    is reg0_exg=8 & A   { exg8l_r0 = A; exg8h_r0 = A; }
EXG_r0Tmp: B    is reg0_exg=9 & B   { exg8l_r0 = B; exg8h_r0 = B; }
EXG_r0Tmp: CC   is reg0_exg=10 & CC { exg8l_r0 = CC; exg8h_r0 = CC;}
EXG_r0Tmp: DP   is reg0_exg=12 & DP { exg8l_r0 = DP; exg8h_r0 = DP;}
EXG_r0Tmp: 0    is reg0_exg=13      { exg16_r0 = 0x0; }
EXG_r0Tmp: 0    is reg0_exg=14      { exg16_r0 = 0x0; }
EXG_r0Tmp: E    is reg0_exg=15 & E  { exg8l_r0 = E; exg8h_r0 = E; }
EXG_r0Tmp: F    is reg0_exg=16 & F  { exg8l_r0 = F; exg8h_r0 = F; }

EXG_r1Tmp: D    is reg1_exg=0 & D   { exg16_r1 = D; }
EXG_r1Tmp: X    is reg1_exg=1 & X   { exg16_r1 = X; }
EXG_r1Tmp: Y    is reg1_exg=2 & Y   { exg16_r1 = Y; }
EXG_r1Tmp: U    is reg1_exg=3 & U   { exg16_r1 = U; }
EXG_r1Tmp: S    is reg1_exg=4 & S   { exg16_r1 = S; }
EXG_r1Tmp: PC   is reg1_exg=5 & PC  { exg16_r1 = inst_next; }
EXG_r1Tmp: W    is reg1_exg=6 & W   { exg16_r1 = 0x0; }
EXG_r1Tmp: V    is reg1_exg=7 & V   { exg16_r1 = 0x0; }
EXG_r1Tmp: A    is reg1_exg=8 & A   { exg8l_r1 = A; exg8h_r1 = A; }
EXG_r1Tmp: B    is reg1_exg=9 & B   { exg8l_r1 = B; exg8h_r1 = B; }
EXG_r1Tmp: CC   is reg1_exg=10 & CC { exg8l_r1 = CC; exg8h_r1 = CC;}
EXG_r1Tmp: DP   is reg1_exg=12 & DP { exg8l_r1 = DP; exg8h_r1 = DP;}
EXG_r1Tmp: 0    is reg1_exg=13      { exg16_r1 = 0x0; }
EXG_r1Tmp: 0    is reg1_exg=14      { exg16_r1 = 0x0; }
EXG_r1Tmp: E    is reg1_exg=15 & E  { exg8l_r1 = E; exg8h_r1 = E; }
EXG_r1Tmp: F    is reg1_exg=16 & F  { exg8l_r1 = F; exg8h_r1 = F; }

EXG_r0Set: D    is reg0_exg=0 & D   { D = exg16_r1; }
EXG_r0Set: X    is reg0_exg=1 & X   { X = exg16_r1; }
EXG_r0Set: Y    is reg0_exg=2 & Y   { Y = exg16_r1; }
EXG_r0Set: U    is reg0_exg=3 & U   { U = exg16_r1; }
EXG_r0Set: S    is reg0_exg=4 & S   { S = exg16_r1; }
EXG_r0Set: PC   is reg0_exg=5 & PC  { PC = exg16_r1; } # TODO must GOTO!
EXG_r0Set: W    is reg0_exg=6 & W   { W = exg16_r1; }
EXG_r0Set: V    is reg0_exg=7 & V   { V = exg16_r1; }
EXG_r0Set: A    is reg0_exg=8 & A   { A = exg8h_r1; }
EXG_r0Set: B    is reg0_exg=9 & B   { B = exg8l_r1; }
EXG_r0Set: CC   is reg0_exg=10 & CC { CC = exg8l_r1; }
EXG_r0Set: DP   is reg0_exg=11 & DP { DP = exg8h_r1; }
EXG_r0Set: 0    is reg0_exg=12      {  }
EXG_r0Set: 0    is reg0_exg=13      {  }
EXG_r0Set: E    is reg0_exg=14 & E  { E = exg8h_r1; }
EXG_r0Set: F    is reg0_exg=15 & F  { F = exg8l_r1; }

EXG_r1Set: D    is reg1_exg=0 & D   { D = exg16_r0; }
EXG_r1Set: X    is reg1_exg=1 & X   { X = exg16_r0; }
EXG_r1Set: Y    is reg1_exg=2 & Y   { Y = exg16_r0; }
EXG_r1Set: U    is reg1_exg=3 & U   { U = exg16_r0; }
EXG_r1Set: S    is reg1_exg=4 & S   { S = exg16_r0; }
EXG_r1Set: PC   is reg1_exg=5 & PC  { PC = exg16_r0; } # TODO must GOTO!
EXG_r1Set: W    is reg1_exg=6 & W   { W = exg16_r0; }
EXG_r1Set: V    is reg1_exg=7 & V   { V = exg16_r0; }
EXG_r1Set: A    is reg1_exg=8 & A   { A = exg8h_r0; }
EXG_r1Set: B    is reg1_exg=9 & B   { B = exg8l_r0; }
EXG_r1Set: CC   is reg1_exg=10 & CC { CC = exg8l_r0; }
EXG_r1Set: DP   is reg1_exg=11 & DP { DP = exg8h_r0; }
EXG_r1Set: 0    is reg1_exg=12      {  }
EXG_r1Set: 0    is reg1_exg=13      {  }
EXG_r1Set: E    is reg1_exg=14 & E  { E = exg8h_r0; }
EXG_r1Set: F    is reg1_exg=15 & F  { F = exg8l_r0; }
@endif

@ifdef M6809
EXG_r0Tmp: D      is reg0_exg=0 & D   { exg16_r0 = D; }
EXG_r0Tmp: X      is reg0_exg=1 & X   { exg16_r0 = X; }
EXG_r0Tmp: Y      is reg0_exg=2 & Y   { exg16_r0 = Y; }
EXG_r0Tmp: U      is reg0_exg=3 & U   { exg16_r0 = U; }
EXG_r0Tmp: S      is reg0_exg=4 & S   { exg16_r0 = S; }
EXG_r0Tmp: PC     is reg0_exg=5 & PC  { exg16_r0 = inst_next; }
EXG_r0Tmp: "inv"  is reg0_exg=6       { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=7       { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: A      is reg0_exg=8 & A   { exg8l_r0 = A; exg8h_r0 = 0xFF; }
EXG_r0Tmp: B      is reg0_exg=9 & B   { exg8l_r0 = B; exg8h_r0 = 0xFF; }
EXG_r0Tmp: CC     is reg0_exg=10 & CC { exg8l_r0 = CC; exg8h_r0 = CC;}
EXG_r0Tmp: DP     is reg0_exg=11 & DP { exg8l_r0 = DP; exg8h_r0 = DP;}
EXG_r0Tmp: "inv"  is reg0_exg=12      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=13      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=14      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=15      { exg16_r0 = 0xFFFF; }

EXG_r1Tmp: D      is reg1_exg=0 & D   { exg16_r1 = D; }
EXG_r1Tmp: X      is reg1_exg=1 & X   { exg16_r1 = X; }
EXG_r1Tmp: Y      is reg1_exg=2 & Y   { exg16_r1 = Y; }
EXG_r1Tmp: U      is reg1_exg=3 & U   { exg16_r1 = U; }
EXG_r1Tmp: S      is reg1_exg=4 & S   { exg16_r1 = S; }
EXG_r1Tmp: PC     is reg1_exg=5 & PC  { exg16_r1 = inst_next; }
EXG_r1Tmp: "inv"  is reg1_exg=6       { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=7       { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: A      is reg1_exg=8 & A   { exg8l_r1 = A; exg8h_r1 = 0xFF; }
EXG_r1Tmp: B      is reg1_exg=9 & B   { exg8l_r1 = B; exg8h_r1 = 0xFF; }
EXG_r1Tmp: CC     is reg1_exg=10 & CC { exg8l_r1 = CC; exg8h_r1 = 0xFF;}
EXG_r1Tmp: DP     is reg1_exg=11 & DP { exg8l_r1 = DP; exg8h_r1 = 0xFF;}
EXG_r1Tmp: "inv"  is reg1_exg=12      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=13      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=14      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=15      { exg16_r1 = 0xFFFF; }

EXG_r0Set: D      is reg0_exg=0 & D   { D = exg16_r1; }
EXG_r0Set: X      is reg0_exg=1 & X   { X = exg16_r1; }
EXG_r0Set: Y      is reg0_exg=2 & Y   { Y = exg16_r1; }
EXG_r0Set: U      is reg0_exg=3 & U   { U = exg16_r1; }
EXG_r0Set: S      is reg0_exg=4 & S   { S = exg16_r1; }
EXG_r0Set: PC     is reg0_exg=5 & PC  { PC = exg16_r1; } # TODO must GOTO!
EXG_r0Set: "inv"  is reg0_exg=6       {  }
EXG_r0Set: "inv"  is reg0_exg=7       {  }
EXG_r0Set: A      is reg0_exg=8 & A   { A = exg8l_r1; }
EXG_r0Set: B      is reg0_exg=9 & B   { B = exg8l_r1; }
EXG_r0Set: CC     is reg0_exg=10 & CC { CC = exg8l_r1; }
EXG_r0Set: DP     is reg0_exg=11 & DP { DP = exg8l_r1; }
EXG_r0Set: "inv"  is reg0_exg=12      {  }
EXG_r0Set: "inv"  is reg0_exg=13      {  }
EXG_r0Set: "inv"  is reg0_exg=14      {  }
EXG_r0Set: "inv"  is reg0_exg=15      {  }

EXG_r1Set: D      is reg1_exg=0 & D   { D = exg16_r0; } # Must to r1 set first so A,D = A,B switch
EXG_r1Set: X      is reg1_exg=1 & X   { X = exg16_r0; }
EXG_r1Set: Y      is reg1_exg=2 & Y   { Y = exg16_r0; }
EXG_r1Set: U      is reg1_exg=3 & U   { U = exg16_r0; }
EXG_r1Set: S      is reg1_exg=4 & S   { S = exg16_r0; }
EXG_r1Set: PC     is reg1_exg=5 & PC  { PC = exg16_r0; } # TODO must GOTO!
EXG_r1Set: "inv"  is reg1_exg=6       {  }
EXG_r1Set: "inv"  is reg1_exg=7       {  }
EXG_r1Set: A      is reg1_exg=8 & A   { A = exg8l_r0; }
EXG_r1Set: B      is reg1_exg=9 & B   { B = exg8l_r0; }
EXG_r1Set: CC     is reg1_exg=10 & CC { CC = exg8l_r0; }
EXG_r1Set: DP     is reg1_exg=11 & DP { DP = exg8l_r0; }
EXG_r1Set: "inv"  is reg1_exg=12      {  }
EXG_r1Set: "inv"  is reg1_exg=13      {  }
EXG_r1Set: "inv"  is reg1_exg=14      {  }
EXG_r1Set: "inv"  is reg1_exg=15      {  }
@endif

EXG_GOTO: is reg0_exg=5 | reg1_exg=5 { goto [PC]; }
EXG_GOTO: is reg0_exg & reg1_exg     {  } # PC not set

# Exchange two registers
:EXG EXG_r0Set, EXG_r1Set    is op=0x1E; EXG_r0Set & EXG_r1Set & EXG_r0Tmp & EXG_r1Tmp & EXG_GOTO
{
    build EXG_r0Tmp;
    build EXG_r1Tmp;
    build EXG_r1Set;
    build EXG_r0Set;
    build EXG_GOTO;
}

All 5 comments

This should do what you want. Also for the 6309 which has a slightly different set of semantics. The approach is a little brute force and there are probably other clever ways, but this lays out all the subtle cases, and the cases when an operand is invalid which have specifically called out semantics.

Also note the GOTO semantics when the PC is one of the targets.

Looking forward to the full language!

# sleigh specification file for Motorola 6809
define endian=big;
define alignment=1;

define space RAM     type=ram_space      size=2  default;
define space register type=register_space size=1;

define register offset=0 size=1 [ A B DP ]; # 8-bit registers A, B, DP
define register offset=0 size=2 [ D ]; # 16-bit D reg. (Same addr. as A/B)
define register offset=8 size=1 [ CC ]; # 8-bit condition code register
define register offset=16 size=2 [ PC X Y U S ]; # 16-bit registers:

define register offset =32 size=2 [ exg16_r0           exg16_r1          ];
define register offset =32 size=1 [ exg8h_r0 exg8l_r0  exg8h_r1 exg8l_r1 ];
define token opbyte (8)
   op    = (0,7)
;

@define M6809 ""

define token data8 (8)
    reg01= (4,7)                                                                
    reg02= (4,7)
    reg11= (0,3)
    reg12= (0,3)
    reg0_exg = (4,7)
    reg1_exg = (0,3)
;

@ifdef M6309
EXG_r0Tmp: D    is reg0_exg=0 & D   { exg16_r0 = D; }
EXG_r0Tmp: X    is reg0_exg=1 & X   { exg16_r0 = X; }
EXG_r0Tmp: Y    is reg0_exg=2 & Y   { exg16_r0 = Y; }
EXG_r0Tmp: U    is reg0_exg=3 & U   { exg16_r0 = U; }
EXG_r0Tmp: S    is reg0_exg=4 & S   { exg16_r0 = S; }
EXG_r0Tmp: PC   is reg0_exg=5 & PC  { exg16_r0 = inst_next; }
EXG_r0Tmp: W    is reg0_exg=6 & W   { exg16_r0 = 0x0; }
EXG_r0Tmp: V    is reg0_exg=7 & V   { exg16_r0 = 0x0; }
EXG_r0Tmp: A    is reg0_exg=8 & A   { exg8l_r0 = A; exg8h_r0 = A; }
EXG_r0Tmp: B    is reg0_exg=9 & B   { exg8l_r0 = B; exg8h_r0 = B; }
EXG_r0Tmp: CC   is reg0_exg=10 & CC { exg8l_r0 = CC; exg8h_r0 = CC;}
EXG_r0Tmp: DP   is reg0_exg=12 & DP { exg8l_r0 = DP; exg8h_r0 = DP;}
EXG_r0Tmp: 0    is reg0_exg=13      { exg16_r0 = 0x0; }
EXG_r0Tmp: 0    is reg0_exg=14      { exg16_r0 = 0x0; }
EXG_r0Tmp: E    is reg0_exg=15 & E  { exg8l_r0 = E; exg8h_r0 = E; }
EXG_r0Tmp: F    is reg0_exg=16 & F  { exg8l_r0 = F; exg8h_r0 = F; }

EXG_r1Tmp: D    is reg1_exg=0 & D   { exg16_r1 = D; }
EXG_r1Tmp: X    is reg1_exg=1 & X   { exg16_r1 = X; }
EXG_r1Tmp: Y    is reg1_exg=2 & Y   { exg16_r1 = Y; }
EXG_r1Tmp: U    is reg1_exg=3 & U   { exg16_r1 = U; }
EXG_r1Tmp: S    is reg1_exg=4 & S   { exg16_r1 = S; }
EXG_r1Tmp: PC   is reg1_exg=5 & PC  { exg16_r1 = inst_next; }
EXG_r1Tmp: W    is reg1_exg=6 & W   { exg16_r1 = 0x0; }
EXG_r1Tmp: V    is reg1_exg=7 & V   { exg16_r1 = 0x0; }
EXG_r1Tmp: A    is reg1_exg=8 & A   { exg8l_r1 = A; exg8h_r1 = A; }
EXG_r1Tmp: B    is reg1_exg=9 & B   { exg8l_r1 = B; exg8h_r1 = B; }
EXG_r1Tmp: CC   is reg1_exg=10 & CC { exg8l_r1 = CC; exg8h_r1 = CC;}
EXG_r1Tmp: DP   is reg1_exg=12 & DP { exg8l_r1 = DP; exg8h_r1 = DP;}
EXG_r1Tmp: 0    is reg1_exg=13      { exg16_r1 = 0x0; }
EXG_r1Tmp: 0    is reg1_exg=14      { exg16_r1 = 0x0; }
EXG_r1Tmp: E    is reg1_exg=15 & E  { exg8l_r1 = E; exg8h_r1 = E; }
EXG_r1Tmp: F    is reg1_exg=16 & F  { exg8l_r1 = F; exg8h_r1 = F; }

EXG_r0Set: D    is reg0_exg=0 & D   { D = exg16_r1; }
EXG_r0Set: X    is reg0_exg=1 & X   { X = exg16_r1; }
EXG_r0Set: Y    is reg0_exg=2 & Y   { Y = exg16_r1; }
EXG_r0Set: U    is reg0_exg=3 & U   { U = exg16_r1; }
EXG_r0Set: S    is reg0_exg=4 & S   { S = exg16_r1; }
EXG_r0Set: PC   is reg0_exg=5 & PC  { PC = exg16_r1; } # TODO must GOTO!
EXG_r0Set: W    is reg0_exg=6 & W   { W = exg16_r1; }
EXG_r0Set: V    is reg0_exg=7 & V   { V = exg16_r1; }
EXG_r0Set: A    is reg0_exg=8 & A   { A = exg8h_r1; }
EXG_r0Set: B    is reg0_exg=9 & B   { B = exg8l_r1; }
EXG_r0Set: CC   is reg0_exg=10 & CC { CC = exg8l_r1; }
EXG_r0Set: DP   is reg0_exg=11 & DP { DP = exg8h_r1; }
EXG_r0Set: 0    is reg0_exg=12      {  }
EXG_r0Set: 0    is reg0_exg=13      {  }
EXG_r0Set: E    is reg0_exg=14 & E  { E = exg8h_r1; }
EXG_r0Set: F    is reg0_exg=15 & F  { F = exg8l_r1; }

EXG_r1Set: D    is reg1_exg=0 & D   { D = exg16_r0; }
EXG_r1Set: X    is reg1_exg=1 & X   { X = exg16_r0; }
EXG_r1Set: Y    is reg1_exg=2 & Y   { Y = exg16_r0; }
EXG_r1Set: U    is reg1_exg=3 & U   { U = exg16_r0; }
EXG_r1Set: S    is reg1_exg=4 & S   { S = exg16_r0; }
EXG_r1Set: PC   is reg1_exg=5 & PC  { PC = exg16_r0; } # TODO must GOTO!
EXG_r1Set: W    is reg1_exg=6 & W   { W = exg16_r0; }
EXG_r1Set: V    is reg1_exg=7 & V   { V = exg16_r0; }
EXG_r1Set: A    is reg1_exg=8 & A   { A = exg8h_r0; }
EXG_r1Set: B    is reg1_exg=9 & B   { B = exg8l_r0; }
EXG_r1Set: CC   is reg1_exg=10 & CC { CC = exg8l_r0; }
EXG_r1Set: DP   is reg1_exg=11 & DP { DP = exg8h_r0; }
EXG_r1Set: 0    is reg1_exg=12      {  }
EXG_r1Set: 0    is reg1_exg=13      {  }
EXG_r1Set: E    is reg1_exg=14 & E  { E = exg8h_r0; }
EXG_r1Set: F    is reg1_exg=15 & F  { F = exg8l_r0; }
@endif

@ifdef M6809
EXG_r0Tmp: D      is reg0_exg=0 & D   { exg16_r0 = D; }
EXG_r0Tmp: X      is reg0_exg=1 & X   { exg16_r0 = X; }
EXG_r0Tmp: Y      is reg0_exg=2 & Y   { exg16_r0 = Y; }
EXG_r0Tmp: U      is reg0_exg=3 & U   { exg16_r0 = U; }
EXG_r0Tmp: S      is reg0_exg=4 & S   { exg16_r0 = S; }
EXG_r0Tmp: PC     is reg0_exg=5 & PC  { exg16_r0 = inst_next; }
EXG_r0Tmp: "inv"  is reg0_exg=6       { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=7       { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: A      is reg0_exg=8 & A   { exg8l_r0 = A; exg8h_r0 = 0xFF; }
EXG_r0Tmp: B      is reg0_exg=9 & B   { exg8l_r0 = B; exg8h_r0 = 0xFF; }
EXG_r0Tmp: CC     is reg0_exg=10 & CC { exg8l_r0 = CC; exg8h_r0 = CC;}
EXG_r0Tmp: DP     is reg0_exg=11 & DP { exg8l_r0 = DP; exg8h_r0 = DP;}
EXG_r0Tmp: "inv"  is reg0_exg=12      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=13      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=14      { exg16_r0 = 0xFFFF; }
EXG_r0Tmp: "inv"  is reg0_exg=15      { exg16_r0 = 0xFFFF; }

EXG_r1Tmp: D      is reg1_exg=0 & D   { exg16_r1 = D; }
EXG_r1Tmp: X      is reg1_exg=1 & X   { exg16_r1 = X; }
EXG_r1Tmp: Y      is reg1_exg=2 & Y   { exg16_r1 = Y; }
EXG_r1Tmp: U      is reg1_exg=3 & U   { exg16_r1 = U; }
EXG_r1Tmp: S      is reg1_exg=4 & S   { exg16_r1 = S; }
EXG_r1Tmp: PC     is reg1_exg=5 & PC  { exg16_r1 = inst_next; }
EXG_r1Tmp: "inv"  is reg1_exg=6       { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=7       { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: A      is reg1_exg=8 & A   { exg8l_r1 = A; exg8h_r1 = 0xFF; }
EXG_r1Tmp: B      is reg1_exg=9 & B   { exg8l_r1 = B; exg8h_r1 = 0xFF; }
EXG_r1Tmp: CC     is reg1_exg=10 & CC { exg8l_r1 = CC; exg8h_r1 = 0xFF;}
EXG_r1Tmp: DP     is reg1_exg=11 & DP { exg8l_r1 = DP; exg8h_r1 = 0xFF;}
EXG_r1Tmp: "inv"  is reg1_exg=12      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=13      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=14      { exg16_r1 = 0xFFFF; }
EXG_r1Tmp: "inv"  is reg1_exg=15      { exg16_r1 = 0xFFFF; }

EXG_r0Set: D      is reg0_exg=0 & D   { D = exg16_r1; }
EXG_r0Set: X      is reg0_exg=1 & X   { X = exg16_r1; }
EXG_r0Set: Y      is reg0_exg=2 & Y   { Y = exg16_r1; }
EXG_r0Set: U      is reg0_exg=3 & U   { U = exg16_r1; }
EXG_r0Set: S      is reg0_exg=4 & S   { S = exg16_r1; }
EXG_r0Set: PC     is reg0_exg=5 & PC  { PC = exg16_r1; } # TODO must GOTO!
EXG_r0Set: "inv"  is reg0_exg=6       {  }
EXG_r0Set: "inv"  is reg0_exg=7       {  }
EXG_r0Set: A      is reg0_exg=8 & A   { A = exg8l_r1; }
EXG_r0Set: B      is reg0_exg=9 & B   { B = exg8l_r1; }
EXG_r0Set: CC     is reg0_exg=10 & CC { CC = exg8l_r1; }
EXG_r0Set: DP     is reg0_exg=11 & DP { DP = exg8l_r1; }
EXG_r0Set: "inv"  is reg0_exg=12      {  }
EXG_r0Set: "inv"  is reg0_exg=13      {  }
EXG_r0Set: "inv"  is reg0_exg=14      {  }
EXG_r0Set: "inv"  is reg0_exg=15      {  }

EXG_r1Set: D      is reg1_exg=0 & D   { D = exg16_r0; } # Must to r1 set first so A,D = A,B switch
EXG_r1Set: X      is reg1_exg=1 & X   { X = exg16_r0; }
EXG_r1Set: Y      is reg1_exg=2 & Y   { Y = exg16_r0; }
EXG_r1Set: U      is reg1_exg=3 & U   { U = exg16_r0; }
EXG_r1Set: S      is reg1_exg=4 & S   { S = exg16_r0; }
EXG_r1Set: PC     is reg1_exg=5 & PC  { PC = exg16_r0; } # TODO must GOTO!
EXG_r1Set: "inv"  is reg1_exg=6       {  }
EXG_r1Set: "inv"  is reg1_exg=7       {  }
EXG_r1Set: A      is reg1_exg=8 & A   { A = exg8l_r0; }
EXG_r1Set: B      is reg1_exg=9 & B   { B = exg8l_r0; }
EXG_r1Set: CC     is reg1_exg=10 & CC { CC = exg8l_r0; }
EXG_r1Set: DP     is reg1_exg=11 & DP { DP = exg8l_r0; }
EXG_r1Set: "inv"  is reg1_exg=12      {  }
EXG_r1Set: "inv"  is reg1_exg=13      {  }
EXG_r1Set: "inv"  is reg1_exg=14      {  }
EXG_r1Set: "inv"  is reg1_exg=15      {  }
@endif

EXG_GOTO: is reg0_exg=5 | reg1_exg=5 { goto [PC]; }
EXG_GOTO: is reg0_exg & reg1_exg     {  } # PC not set

# Exchange two registers
:EXG EXG_r0Set, EXG_r1Set    is op=0x1E; EXG_r0Set & EXG_r1Set & EXG_r0Tmp & EXG_r1Tmp & EXG_GOTO
{
    build EXG_r0Tmp;
    build EXG_r1Tmp;
    build EXG_r1Set;
    build EXG_r0Set;
    build EXG_GOTO;
}

It works, great job!
There will be a pull request when ghidra is fully open sourced.

Awesome!

Has M6809 support been PRed back? I would really appreciate this functionality. Thx

Now there is a PR #1201 for M6809 :-)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gemini00 picture gemini00  路  3Comments

Merculous picture Merculous  路  3Comments

rrivera1849 picture rrivera1849  路  3Comments

toor-de-force picture toor-de-force  路  3Comments

huettenhain picture huettenhain  路  3Comments