From 288a857e4796ef230f541f242c6d55b9ff85abd9 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Mon, 20 Jul 2020 11:54:00 -0700 Subject: [PATCH] Change PLP handling The "smart" PLP handler tries to recover the flags from an earlier PHP. The non-smart version just marks all the flags as indeterminate. This doesn't work well on the 65816 in native mode, because having the M/X flags in an indeterminate state is rarely what you want. Code rarely uses PLP to reset the flags to a specific state, preferring explicit SEP/REP. The analyzer is more likely to get the correct answer by simply leaving the flags in their prior state. A test case has been added to 20052-branches-and-banks, which now has "smart PLP" disabled. --- SourceGen/CodeAnalysis.cs | 17 +++++++-- SourceGen/RuntimeData/Help/settings.html | 3 +- SourceGen/SGTestData/20052-branches-and-banks | Bin 224 -> 234 bytes .../SGTestData/20052-branches-and-banks.dis65 | 6 +-- .../20052-branches-and-banks_64tass.S | 28 ++++++++++---- .../20052-branches-and-banks_Merlin32.S | 25 +++++++++---- .../Expected/20052-branches-and-banks_acme.S | 3 +- .../Expected/20052-branches-and-banks_cc65.S | 28 ++++++++++---- .../20052-branches-and-banks_cc65.cfg | 2 +- .../Source/20052-branches-and-banks.S | 35 ++++++++++++++++++ 10 files changed, 116 insertions(+), 31 deletions(-) diff --git a/SourceGen/CodeAnalysis.cs b/SourceGen/CodeAnalysis.cs index 9b50978..932738b 100644 --- a/SourceGen/CodeAnalysis.cs +++ b/SourceGen/CodeAnalysis.cs @@ -804,12 +804,12 @@ namespace SourceGen { // it around like one. The E-flag is always carried over from the previous // instruction. - int backOffsetLimit = plpOffset - 128; // arbitrary 128-byte reach - if (backOffsetLimit < 0) { - backOffsetLimit = 0; - } StatusFlags flags = StatusFlags.AllIndeterminate; if (mAnalysisParameters.SmartPlpHandling) { + int backOffsetLimit = plpOffset - 128; // arbitrary 128-byte reach + if (backOffsetLimit < 0) { + backOffsetLimit = 0; + } for (int offset = plpOffset - 1; offset >= backOffsetLimit; offset--) { Anattrib attr = mAnattribs[offset]; if (!attr.IsInstructionStart || !attr.IsVisited) { @@ -824,6 +824,15 @@ namespace SourceGen { } } + if (flags == StatusFlags.AllIndeterminate && + (mCpuDef.Type == CpuDef.CpuType.Cpu65816 || + mCpuDef.Type == CpuDef.CpuType.Cpu65802)) { + // Having indeterminate M/X flags is really bad. If "smart" handling failed or + // is disabled, copy flags from previous instruction. + flags.M = mAnattribs[plpOffset].StatusFlags.M; + flags.X = mAnattribs[plpOffset].StatusFlags.X; + } + // Transfer the 'E' flag. flags.E = mAnattribs[plpOffset].StatusFlags.E; return flags; diff --git a/SourceGen/RuntimeData/Help/settings.html b/SourceGen/RuntimeData/Help/settings.html index 2b30375..072244a 100644 --- a/SourceGen/RuntimeData/Help/settings.html +++ b/SourceGen/RuntimeData/Help/settings.html @@ -273,7 +273,8 @@ improve automatic operand formatting.

If "smart PLP handling" is checked, the analyzer will try to use the processor status flags from a nearby PHP when a PLP is encountered. If not enabled, all flags are set to -"indeterminate" following a PLP.

+"indeterminate" following a PLP, except for the M/X +flags on the 65816, which are left unmodified.

If "smart PLB handling" is checked, the analyzer will watch for code patterns like PLB preceded by PHK, and generate appropriate Data Bank Register changes. If not enabled, diff --git a/SourceGen/SGTestData/20052-branches-and-banks b/SourceGen/SGTestData/20052-branches-and-banks index db4c8cf724ddc0b6ee3dcd6a18c7501e0917e7b8..d49366348bf642da1b42d72fa84d93e21f9b1d0d 100644 GIT binary patch delta 39 pcmaFB_=<7DDTPA@94i?Z9vQ4;&{+BE)gut^5Re1r9Wr>84FFI^5tIM` delta 29 jcmaFG_<(W3DKYQW>l>Uxlz{lv+6E_u2B$v_POq{7#)1ug diff --git a/SourceGen/SGTestData/20052-branches-and-banks.dis65 b/SourceGen/SGTestData/20052-branches-and-banks.dis65 index 58e5da9..a23d28f 100644 --- a/SourceGen/SGTestData/20052-branches-and-banks.dis65 +++ b/SourceGen/SGTestData/20052-branches-and-banks.dis65 @@ -1,8 +1,8 @@ ### 6502bench SourceGen dis65 v1.0 ### { "_ContentVersion":4, -"FileDataLength":224, -"FileDataCrc32":2055368095, +"FileDataLength":234, +"FileDataCrc32":1224113674, "ProjectProps":{ "CpuName":"65816", "IncludeUndocumentedInstr":false, @@ -15,7 +15,7 @@ "MinCharsForString":4, "SeekNearbyTargets":true, "UseRelocData":false, -"SmartPlpHandling":true, +"SmartPlpHandling":false, "SmartPlbHandling":false}, "PlatformSymbolFileIdentifiers":["PROJ:20050-branches-and-banks.sym65"], diff --git a/SourceGen/SGTestData/Expected/20052-branches-and-banks_64tass.S b/SourceGen/SGTestData/Expected/20052-branches-and-banks_64tass.S index 0b2c03f..af40eb0 100644 --- a/SourceGen/SGTestData/Expected/20052-branches-and-banks_64tass.S +++ b/SourceGen/SGTestData/Expected/20052-branches-and-banks_64tass.S @@ -109,14 +109,28 @@ fwdchk nop L543280 jsr skip+$540000 nop - phk - plb - lda $544280 - jsl $544280 + rep #$30 + .al + .xl + php + lda #$0000 + sep #$30 + .as + .xs + lda #$00 + plp + lda #$ea nop - lda $4280 - jsr $544280 - jsr ($544280,x) + sep #$30 + php + lda #$00 + rep #$30 + .al + .xl + lda #$0000 + plp + lda #$eaea + rep #$30 nop rtl diff --git a/SourceGen/SGTestData/Expected/20052-branches-and-banks_Merlin32.S b/SourceGen/SGTestData/Expected/20052-branches-and-banks_Merlin32.S index dd09f2e..af43dbf 100644 --- a/SourceGen/SGTestData/Expected/20052-branches-and-banks_Merlin32.S +++ b/SourceGen/SGTestData/Expected/20052-branches-and-banks_Merlin32.S @@ -103,14 +103,25 @@ fwdchk nop L543280 jsr skip nop - phk - plb - ldal $544280 - jsl $544280 + rep #$30 + mx %00 + php + lda #$0000 + sep #$30 + mx %11 + lda #$00 + plp + lda #$ea nop - lda $4280 - jsr $4280 - jsr ($4280,x) + sep #$30 + php + lda #$00 + rep #$30 + mx %00 + lda #$0000 + plp + lda #$eaea + rep #$30 nop rtl diff --git a/SourceGen/SGTestData/Expected/20052-branches-and-banks_acme.S b/SourceGen/SGTestData/Expected/20052-branches-and-banks_acme.S index 9c3c485..f9a2e1c 100644 --- a/SourceGen/SGTestData/Expected/20052-branches-and-banks_acme.S +++ b/SourceGen/SGTestData/Expected/20052-branches-and-banks_acme.S @@ -7,5 +7,6 @@ !hex 3254af163254af7d3254af163254af7d3254ad1732ad1532ad7e32ad7c32ea20 !hex 1632201732201832207d32207e32207f32eaa200fc1932fc7a32206e32207132 !hex 206832206b3220743220773280187c19327c7a326c08106c0810dc0810dc0810 - !hex 7d3254eaea60200e20ea4babaf80425422804254eaad8042208042fc8042ea6b + !hex 7d3254eaea60200e20eac23008a90000e230a90028a9eaeae23008a900c230a9 + !hex 000028a9eaeac230ea6b } ;!pseudopc diff --git a/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.S b/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.S index cbca746..6b68221 100644 --- a/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.S +++ b/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.S @@ -111,14 +111,28 @@ fwdchk: nop L543280: jsr skip nop - phk - plb - lda $544280 - jsl $544280 + rep #$30 + .a16 + .i16 + php + lda #$0000 + sep #$30 + .a8 + .i8 + lda #$00 + plp + lda #$ea nop - lda $4280 - jsr $4280 - jsr ($4280,x) + sep #$30 + php + lda #$00 + rep #$30 + .a16 + .i16 + lda #$0000 + plp + lda #$eaea + rep #$30 nop rtl diff --git a/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.cfg b/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.cfg index 49008c6..19491ea 100644 --- a/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.cfg +++ b/SourceGen/SGTestData/Expected/20052-branches-and-banks_cc65.cfg @@ -5,7 +5,7 @@ MEMORY { # MEM001: file=%O, start=$440000, size=28; # MEM002: file=%O, start=$44ffc0, size=15; # MEM003: file=%O, start=$2000, size=32; -# MEM004: file=%O, start=$543210, size=138; +# MEM004: file=%O, start=$543210, size=148; } SEGMENTS { CODE: load=MAIN, type=rw; diff --git a/SourceGen/SGTestData/Source/20052-branches-and-banks.S b/SourceGen/SGTestData/Source/20052-branches-and-banks.S index 369aeae..e8ee3e4 100644 --- a/SourceGen/SGTestData/Source/20052-branches-and-banks.S +++ b/SourceGen/SGTestData/Source/20052-branches-and-banks.S @@ -130,4 +130,39 @@ fwdchk: nxt54b: jsr skip ;EDIT: set to "skip" label + nop + + +; Test the non-"smart" PLP affects on the M/X flags. +; EDIT: disable "smart PLP" for this project + rep #$30 + .a16 + .i16 + php + lda #$0000 + sep #$30 + .a8 + .i8 + lda #$00 + plp ;smart->long, unsmart->short + lda #$ea + nop + + sep #$30 + .a8 + .i8 + php + lda #$00 + rep #$30 + .a16 + .i16 + lda #$0000 + plp ;smart->short, unsmart->long + lda #$eaea + + rep #$30 + .a16 + .i16 + nop + rtl