From 2c4fac9f76ac2a4c8aebae68dfc5d28cbe41c36e Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Thu, 4 Sep 2025 11:30:05 -0700 Subject: [PATCH] Output big-endian macro for 64tass If we see a big-endian value when generating code for 64tass, output a macro and make use of it. (issue #175) --- SourceGen/AsmGen/AsmTass64.cs | 41 +++++++++++++++---- .../Expected/20000-numeric-types_64tass.S | 5 ++- .../Expected/20020-operand-formats_64tass.S | 11 +++-- .../20030-labels-and-symbols_64tass.S | 5 ++- .../20032-labels-and-symbols_64tass.S | 5 ++- .../Expected/20120-char-encoding-a_64tass.S | 14 +++++-- .../Expected/20130-char-encoding-p_64tass.S | 14 +++++-- .../Expected/20140-char-encoding-s_64tass.S | 14 +++++-- .../Expected/20182-extension-scripts_64tass.S | 5 ++- 9 files changed, 85 insertions(+), 29 deletions(-) diff --git a/SourceGen/AsmGen/AsmTass64.cs b/SourceGen/AsmGen/AsmTass64.cs index 8d4eaeb..deff62e 100644 --- a/SourceGen/AsmGen/AsmTass64.cs +++ b/SourceGen/AsmGen/AsmTass64.cs @@ -118,6 +118,12 @@ namespace SourceGen.AsmGen { /// private CharEncoding.Encoding mCurrentEncoding; + /// + /// True if we defined macros for big-endian numeric values. + /// + private bool mBigEndianMacrosDefined; + private const string BIG_ENDIAN_16_MACRO = "bigendian"; + /// /// Output mode; determines how ORG is handled. /// @@ -173,6 +179,8 @@ namespace SourceGen.AsmGen { { "StrDci", ".shift" } }); + private const string MACRO_DIRECTIVE = ".macro"; + // IGenerator public void GetDefaultDisplayFormat(out PseudoOp.PseudoOpNames pseudoOps, @@ -355,7 +363,7 @@ namespace SourceGen.AsmGen { // need that. mCurrentEncoding = CharEncoding.Encoding.C64Petscii; - CheckAsciiFormats(out bool hasAscii, out bool hasHighAscii); + ScanFormats(out bool hasAscii, out bool hasHighAscii, out bool hasBigEndian); if (hasHighAscii) { OutputLine(string.Empty, ".enc", '"' + HIGH_ASCII_ENC_NAME + '"', string.Empty); OutputLine(string.Empty, ".cdef", "$20,$7e,$a0", string.Empty); @@ -366,11 +374,17 @@ namespace SourceGen.AsmGen { OutputLine(string.Empty, ".cdef", "$20,$7e,$20", string.Empty); mCurrentEncoding = CharEncoding.Encoding.Ascii; } + if (hasBigEndian) { + OutputLine(BIG_ENDIAN_16_MACRO, MACRO_DIRECTIVE, string.Empty, string.Empty); + OutputLine(string.Empty, ".byte", "(\\1)>>8,(\\1)&$ff", string.Empty); + OutputLine(string.Empty, ".endmacro", string.Empty, string.Empty); + mBigEndianMacrosDefined = true; + } } - private void CheckAsciiFormats(out bool hasAscii, out bool hasHighAscii) { + private void ScanFormats(out bool hasAscii, out bool hasHighAscii, out bool hasBigEndian) { int offset = 0; - hasAscii = hasHighAscii = false; + hasAscii = hasHighAscii = hasBigEndian = false; while (offset < Project.FileData.Length) { Anattrib attr = Project.GetAnattrib(offset); FormatDescriptor dfd = attr.DataDescriptor; @@ -380,9 +394,11 @@ namespace SourceGen.AsmGen { hasAscii = true; } else if (dfd.FormatSubType == FormatDescriptor.SubType.HighAscii) { hasHighAscii = true; + } else if (dfd.FormatType == FormatDescriptor.Type.NumericBE) { + hasBigEndian = true; } } - if (hasAscii && hasHighAscii) { + if (hasAscii && hasHighAscii && hasBigEndian) { return; } @@ -541,15 +557,20 @@ namespace SourceGen.AsmGen { break; case FormatDescriptor.Type.NumericBE: opcodeStr = sDataOpNames.GetDefineBigData(length); - if ((string.IsNullOrEmpty(opcodeStr))) { - // Nothing defined, output as comma-separated single-byte values. - GenerateShortSequence(offset, length, out opcodeStr, out operandStr); - } else { + if (string.IsNullOrEmpty(opcodeStr) && length == 2) { + // Special handling for 16-bit big-endian operands. + Debug.Assert(mBigEndianMacrosDefined); + opcodeStr = BIG_ENDIAN_16_MACRO; + } + if (!(string.IsNullOrEmpty(opcodeStr))) { UpdateCharacterEncoding(dfd); operand = RawData.GetWord(data, offset, length, true); operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable, Localizer.LabelMap, dfd, operand, length, PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix); + } else { + // Nothing defined, output as comma-separated single-byte values. + GenerateShortSequence(offset, length, out opcodeStr, out operandStr); } break; case FormatDescriptor.Type.Fill: @@ -784,11 +805,13 @@ namespace SourceGen.AsmGen { // IGenerator public void OutputLine(string label, string opcode, string operand, string comment) { - // Break the line if the label is long and it's not a .EQ/.VAR directive. + // Break the line if the label is long and it's not a .EQ/.VAR/.MACRO directive. if (!string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(opcode) && !string.Equals(opcode, sDataOpNames.EquDirective, StringComparison.InvariantCultureIgnoreCase) && !string.Equals(opcode, sDataOpNames.VarDirective, + StringComparison.InvariantCultureIgnoreCase) && + !string.Equals(opcode, MACRO_DIRECTIVE, StringComparison.InvariantCultureIgnoreCase)) { if (mLabelNewLine == GenCommon.LabelPlacement.PreferSeparateLine || diff --git a/SourceGen/SGTestData/Expected/20000-numeric-types_64tass.S b/SourceGen/SGTestData/Expected/20000-numeric-types_64tass.S index 6951418..53843f4 100644 --- a/SourceGen/SGTestData/Expected/20000-numeric-types_64tass.S +++ b/SourceGen/SGTestData/Expected/20000-numeric-types_64tass.S @@ -3,6 +3,9 @@ .cpu "6502" .enc "sg_hiascii" .cdef $20,$7e,$a0 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro * = $1000 bit L1448 jsr L14A8 @@ -29,7 +32,7 @@ .long $112233 .dword $11223344 .byte $11 - .byte $11,$22 + bigendian $1122 .byte $11,$22,$33 .byte $11,$22,$33,$44 .fill 2,$00 diff --git a/SourceGen/SGTestData/Expected/20020-operand-formats_64tass.S b/SourceGen/SGTestData/Expected/20020-operand-formats_64tass.S index 8e9af52..ab624a7 100644 --- a/SourceGen/SGTestData/Expected/20020-operand-formats_64tass.S +++ b/SourceGen/SGTestData/Expected/20020-operand-formats_64tass.S @@ -4,6 +4,9 @@ .cdef $20,$7e,$a0 .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro * = $1000 lda $01 lda $0102 @@ -68,13 +71,13 @@ more_ascii .byte 'h' .byte $80 .word skipdata .long skipdata - .byte $10,$5d + bigendian skipdata .byte more_ascii .word more_ascii .long more_ascii .dword more_ascii - .byte $10,$81 + bigendian more_ascii .byte '[' .byte '{' .byte '|' @@ -107,8 +110,8 @@ L10A4 nop .byte 255 .word 1 .word 65534 - .byte $00,$02 - .byte $ff,$fd + bigendian 2 + bigendian 65533 .long 66051 .long 16776957 .dword 16909060 diff --git a/SourceGen/SGTestData/Expected/20030-labels-and-symbols_64tass.S b/SourceGen/SGTestData/Expected/20030-labels-and-symbols_64tass.S index a4d241f..da997ed 100644 --- a/SourceGen/SGTestData/Expected/20030-labels-and-symbols_64tass.S +++ b/SourceGen/SGTestData/Expected/20030-labels-and-symbols_64tass.S @@ -3,6 +3,9 @@ .cpu "6502" .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro BMI1 = $30 ;opcode mnemonic zip = $cd absl = $1029 @@ -51,7 +54,7 @@ start lda #zip .word start >> 8 .word start+1 .word start >> 8 - .byte $fe,$ed + bigendian absh .long zip .long absh .long absh >> 8 diff --git a/SourceGen/SGTestData/Expected/20032-labels-and-symbols_64tass.S b/SourceGen/SGTestData/Expected/20032-labels-and-symbols_64tass.S index 6d23c89..fca5e2f 100644 --- a/SourceGen/SGTestData/Expected/20032-labels-and-symbols_64tass.S +++ b/SourceGen/SGTestData/Expected/20032-labels-and-symbols_64tass.S @@ -3,6 +3,9 @@ .cpu "65816" .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro BMI1 = $30 ;opcode mnemonic zip = $cd absl = $1029 @@ -103,7 +106,7 @@ start clc .word 0+(start & $ffff)+1 .word start >> 8 .word start >> 16 - .byte $fe,$ed + bigendian absh .long zip .long absh .long absh >> 8 diff --git a/SourceGen/SGTestData/Expected/20120-char-encoding-a_64tass.S b/SourceGen/SGTestData/Expected/20120-char-encoding-a_64tass.S index 93ca00e..569ac48 100644 --- a/SourceGen/SGTestData/Expected/20120-char-encoding-a_64tass.S +++ b/SourceGen/SGTestData/Expected/20120-char-encoding-a_64tass.S @@ -4,6 +4,9 @@ .cdef $20,$7e,$a0 .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro * = $1000 lda #'A' lda #'A' | $80 @@ -42,10 +45,13 @@ .word 'd' .enc "screen" .word 'd' - .byte $00,$45 - .byte $00,$c5 - .byte $00,$c5 - .byte $00,$45 + .enc "sg_ascii" + bigendian 'E' + bigendian 'E' | $80 + .enc "none" + bigendian 'E' + .enc "screen" + bigendian 'E' .byte $80 .enc "sg_ascii" .text "low ASCII str" diff --git a/SourceGen/SGTestData/Expected/20130-char-encoding-p_64tass.S b/SourceGen/SGTestData/Expected/20130-char-encoding-p_64tass.S index 76c8773..25fa702 100644 --- a/SourceGen/SGTestData/Expected/20130-char-encoding-p_64tass.S +++ b/SourceGen/SGTestData/Expected/20130-char-encoding-p_64tass.S @@ -4,6 +4,9 @@ .cdef $20,$7e,$a0 .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro * = $1000 lda #'A' lda #'A' | $80 @@ -42,10 +45,13 @@ .word 'd' .enc "screen" .word 'd' - .byte $00,$45 - .byte $00,$c5 - .byte $00,$c5 - .byte $00,$45 + .enc "sg_ascii" + bigendian 'E' + bigendian 'E' | $80 + .enc "none" + bigendian 'E' + .enc "screen" + bigendian 'E' .byte $80 .enc "sg_ascii" .text "low ASCII str" diff --git a/SourceGen/SGTestData/Expected/20140-char-encoding-s_64tass.S b/SourceGen/SGTestData/Expected/20140-char-encoding-s_64tass.S index 4d3cf5f..2d7bed3 100644 --- a/SourceGen/SGTestData/Expected/20140-char-encoding-s_64tass.S +++ b/SourceGen/SGTestData/Expected/20140-char-encoding-s_64tass.S @@ -4,6 +4,9 @@ .cdef $20,$7e,$a0 .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro * = $1000 lda #'A' lda #'A' | $80 @@ -42,10 +45,13 @@ .word 'd' .enc "screen" .word 'd' - .byte $00,$45 - .byte $00,$c5 - .byte $00,$c5 - .byte $00,$45 + .enc "sg_ascii" + bigendian 'E' + bigendian 'E' | $80 + .enc "none" + bigendian 'E' + .enc "screen" + bigendian 'E' .byte $80 .enc "sg_ascii" .text "low ASCII str" diff --git a/SourceGen/SGTestData/Expected/20182-extension-scripts_64tass.S b/SourceGen/SGTestData/Expected/20182-extension-scripts_64tass.S index 7a30613..8e0934d 100644 --- a/SourceGen/SGTestData/Expected/20182-extension-scripts_64tass.S +++ b/SourceGen/SGTestData/Expected/20182-extension-scripts_64tass.S @@ -3,6 +3,9 @@ .cdef $20,$7e,$a0 .enc "sg_ascii" .cdef $20,$7e,$20 +bigendian .macro + .byte (\1)>>8,(\1)&$ff + .endmacro PrintInlineL1String = $011000 PrintInlineL2String = $012000 PrintInlineDciString = $013000 @@ -48,7 +51,7 @@ PrintInlineRev8String rts PrintInlineNullString rts data01 .word 4386 - .byte $33,$44 + bigendian $3344 .dword $88776655 .byte $99,$88,$77,$66 .byte 'f'