Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M16C INDEXBD instruction does not affect succeeding MOV instruction #7504

Open
dikidera opened this issue Feb 14, 2025 · 4 comments
Open

M16C INDEXBD instruction does not affect succeeding MOV instruction #7504

dikidera opened this issue Feb 14, 2025 · 4 comments
Assignees
Labels
Feature: Processor/M16C Status: Triage Information is being gathered

Comments

@dikidera
Copy link

dikidera commented Feb 14, 2025

Image

We can see INDEXBD setting the 0x3009 register to the appropriate value, however the next instruction which is a MOV never adds this register.

The appropriate execution must be MOV.B:S R0L, (DAT_000414 + byteIndexOffset) but here we see it is never added via a INT_ADD pcode and I propose this is an actual bug.

In C pseudo code the pcode must do the following:

*(DAT_000414 + byteIndexOffset) = R0L;

If required this bug report may be merged with my other one that was made into a discussion.

@dikidera
Copy link
Author

dikidera commented Feb 14, 2025

Adding further information that may be more relevant.

      decendent constructors for decision node (complete tree dump ordered by line number):
      : {line# 1452} BRK
      : {line# 3053} MOV.B:S <R0L>, <dst2B>
   check pattern[1 of 2] instruction: {line# 1452} BRK
      (  byte pattern: mask=11111111.00000000.00000000.00000000
                 bytes[0-3]=00010000.00010100.00000100.11100010
                match-value=00000000.00000000.00000000.00000000 Failed
      ) -and- (
         context pattern: mask=00011000.00000000.00000000.00000000
                context(0..31)=00001000.00000000.00000000.00000000
                   match-value=00001000.00000000.00000000.00000000 Matched
                     phase(3,4) == 0x1 Match
      ) Failed
   check pattern[2 of 2] instruction: {line# 3053} MOV.B:S <R0L>, <dst2B>
      (  byte pattern: mask=11001111.00000000.00000000.00000000
                 bytes[0-3]=00010000.00010100.00000100.11100010
                match-value=00000000.00000000.00000000.00000000 Matched
      ) -and- (
         context pattern: mask=00011000.00000000.00000000.00000000
                context(0..31)=00001000.00000000.00000000.00000000
                   match-value=00001000.00000000.00000000.00000000 Matched
                     phase(3,4) == 0x1 Match
      ) Matched
      R0L: resolving...
         R0L: register R0L (size:1)
      dst2B: resolving...
         decide on instruction bits: byte-offset=0, bitrange=(2,3), value=0x1, bytes=00(01)0000
            decendent constructors for decision node (complete tree dump ordered by line number):
             dst2B: {line# 538} <imm16_dat>
             dst2B: {line# 539} [<imm16_dat>]
         check pattern[1 of 2] dst2B: {line# 539} [<imm16_dat>]
            (  byte pattern: mask=00110000.00000000.00000000.00000000
                       bytes[0-3]=00010000.00010100.00000100.11100010
                      match-value=00010000.00000000.00000000.00000000 Matched
            ) -and- (
               context pattern: mask=00000100.00000000.00000000.00000000
                      context(0..31)=00001000.00000000.00000000.00000000
                         match-value=00000100.00000000.00000000.00000000 Failed
                           indDst(5,5) == 0x1 Failed (=0x0)
            ) Failed
         check pattern[2 of 2] dst2B: {line# 538} <imm16_dat>
            byte pattern: mask=00110000.00000000.00000000.00000000
                    bytes[0-3]=00010000.00010100.00000100.11100010
                   match-value=00010000.00000000.00000000.00000000 Matched
            imm16_dat: TokenField = 0x414

Prototype parse successful: MOV.B:S R0L,0x000414
Instruction length = 3 bytes
Instr Mask:  11111111.00000000.00000000
Instr Value: 00010000.00000000.00000000
Op-0 Mask:   00000000.00000000.00000000
Op-0 Value:  00000000.00000000.00000000
Op-1 Mask:   00000000.11111111.11111111
Op-1 Value:  00000000.00010100.00000100
DebugSleighInstructionParse.java> Finished!

We can see the instruction matches to pattern check pattern[2 of 2] instruction: {line# 3053} MOV.B:S <R0L>, <dst2B>

But in M16C/80 slaspec file we have

# dst2... Handle 2-bit encoded Destination specified by b1_d2
# Variable length pattern starting at instruction byte b1
# TODO? Certain uses of dst2 should exclude the R0 case (b1_d2=0)
# 1-Byte destination value/location specified by 2-bit encoding (b1_d2)
dst2B: R0L                    is b1_d2=0 & R0L                      { export R0L; }
dst2B: imm16_dat              is b1_d2=1; imm16_dat                 { export *:1 imm16_dat; }
dst2B: [imm16_dat]            is indDst=1 & b1_d2=1; imm16_dat      { ptr:3 = imm16_dat; ptr = *:3 ptr; export *:1 ptr; }
dst2B: imm8_dat^":8"^[SB]     is b1_d2=2 & SB; imm8_dat             { ptr:3 = SB + imm8_dat; export *:1 ptr; }
dst2B: [imm8_dat^":8"^[SB]]   is indDst=1 & b1_d2=2 & SB; imm8_dat  { ptr:3 = SB + imm8_dat; ptr = *:3 ptr; export *:1 ptr; }
dst2B: simm8_dat^":8"^[FB]    is b1_d2=3 & FB; simm8_dat            { ptr:3 = FB + simm8_dat; export *:1 ptr; }
dst2B: [simm8_dat^":8"^[FB]]  is indDst=1 & b1_d2=3 & FB; simm8_dat { ptr:3 = FB + simm8_dat; ptr = *:3 ptr; export *:1 ptr; }

Interestingly the INDEXBD documentation says that only MOV.B:G format can be used but we can see that the compiler has emitted a short format in the form of MOV.B:S.

Instruction which is modified by INDEXBD
The dest of
ABS, ADC, ADCF, ADD:G* 1 * 2 , AND, CLIP, CMP:G* 1 , DEC, INC, MAX, MIN, MOV:G* 1 * 3 ,
MUL, MULU, NEG, NOT, OR, POP, ROLC, RORC, ROT, SBB, SHA, SHL, STNZ, STZ,
STZX, SUB, TST, XCHG, XOR.
The src of
DIV, DIVU, DIVX, PUSH
*1 You can only specify G format.
*2 The SP can not be used in dest of ADD instruction.
*3 The dsp:8[SP] can not be used in src or dest of MOV instruction.
Only above instructions can be used next to INDEXBD instruction.

So I am now questioning if the compiler that emitted this code was wrong.

@GhidorahRex
Copy link
Collaborator

I definitely think the compiler is in the wrong here. I double-checked the disassembly of the MOV.B:S instruction and it's correct. There shouldn't be a byteoffset added here.

@dikidera
Copy link
Author

dikidera commented Feb 14, 2025

I definitely think the compiler is in the wrong here. I double-checked the disassembly of the MOV.B:S instruction and it's correct. There shouldn't be a byteoffset added here.

If behaviour still works as expected, should Ghidra emulate this behaviour regardless of what the specs say? I do not currently posses the hardware to test if the actual CPU modifies the memory offset. But the code I have did run on actual hardware at some point.

I will have to investigate. The bug report should be re-classified as something else as to not confuse others.

@GhidorahRex
Copy link
Collaborator

If behaviour still works as expected, should Ghidra emulate this behaviour regardless of what the specs say? I do not currently posses the hardware to test if the actual CPU modifies the memory offset. But the code I have did run on actual hardware at some point.

I will have to investigate. The bug report should be re-classified as something else as to not confuse others.

Yes, if the behavior works as expected, then Ghidra should emulate it correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature: Processor/M16C Status: Triage Information is being gathered
Projects
None yet
Development

No branches or pull requests

3 participants