Author Topic: Cleaning up a bit of 6800 assembly code  (Read 3985 times)

0 Members and 1 Guest are viewing this topic.

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #25 on: December 06, 2022, 05:55:55 am »
So, I did what I thought of before - assembled it for 6809 and lo, it worked. I had to adjust the source to keep the assembler used happy, but the instructions are unchanged. At least, unchanged by me, the assembler did its usual thing of converting the DEX instruction (which 6809 does not have) into LEAX -1,X .


Code: [Select]

  0000 20  0C              BRA    CONVERT
                   
  0002 00            TEMP5  FCB    0
                   
  0003 00            BINV0  FCB    0        ; BIG ENDIAN
  0004 00            BINV1  FCB    0
  0005 00            BINV2  FCB    0
                   
  0006 00            READ0  FCB    0        ; CHECKSUM BYTE
  0007 01                    FCB    1        ; LITTLE ENDIAN VALUE
  0008 02                    FCB    2        ; 7,654,321
  0009 03                    FCB    3
  000A 04                    FCB    4
  000B 05                    FCB    5
  000C 06                    FCB    6
  000D 07            READ7  FCB    7        ; FIRST DIGIT
                   
  000E 0F  03      CONVERT CLR    BINV0    ; RESULT = 0
  0010 0F  04              CLR    BINV1
  0012 0F  05              CLR    BINV2
  0014 8E  000D            LDX    #READ7    ; POINT TO FIRST DIGIT
 >0017 7E  003A            JMP    FIRST
                   
  001A 96  03      LOOP    LDAA  BINV0    ; MULTIPLY BINARY VALUE BY 10
  001C 97  02              STAA  TEMP5
  001E DC  04              LDD    BINV1    ; 2 SHIFTS = MULTIPLY BY 4
  0020 58                    ASLB
  0021 49                    ROLA
  0022 09  02              ROL    TEMP5
  0024 58                    ASLB
  0025 49                    ROLA
  0026 09  02              ROL    TEMP5
  0028 DB  05              ADDB  BINV2    ; ADD THE ORIGINAL = MULTIPLY BY 5
  002A 99  04              ADCA  BINV1
  002C DD  04              STD    BINV1
  002E 96  02              LDAA  TEMP5
  0030 99  03              ADCA  BINV0
  0032 97  03              STAA  BINV0
  0034 08  05              ASL    BINV2    ; 1 SHIFT = MULTIPLY BY 10
  0036 09  04              ROL    BINV1
  0038 09  03              ROL    BINV0
                   
  003A A6  84      FIRST  LDAA  0,X      ; ADD IN NEXT DIGIT
  003C 9B  05              ADDA  BINV2
  003E 97  05              STAA  BINV2
  0040 24  06              BCC    NEXT
  0042 0C  04              INC    BINV1
  0044 26  02              BNE    NEXT
  0046 0C  03              INC    BINV0
  0048 30  1F      NEXT    DEX
  004A 8C  0006            CPX    #READ0    ; ALL DONE?
  004D 26  CB              BNE    LOOP
  004F 39                    RTS

0 ERROR(S) DETECTED

SYMBOL TABLE:

BINV0  0003  BINV1  0004  BINV2  0005  CONVER 000E  FIRST  003A  LOOP  001A  NEXT  0048 
READ0  0006  READ7  000D  TEMP5  0002 

    +++GET EETEST.BIN.1
    +++MON
    -  SP=C073  US=C073  DP=00  IX=CC9C  IY=C847
    -  PC=D379  A=4E  B=00  CC: E F - I - Z - -
  >E 0000-004F
  - 0000  200C0000 00000001 02030405 06070F03    ...............
  - 0010  0F040F05 8E000D7E 003A9603 9702DC04  .......~.:......
  - 0020  58490902 58490902 DB059904 DD049602  XI..XI..........
  - 0030  99039703 08050904 0903A684 9B059705  ................
  - 0040  24060C04 26020C03 301F8C00 0626CB39  $...&...0....&.9
  >^P  PC=D379 0000
  >B 004F
  >G
    -  SP=C073  US=C073  DP=00  IX=0006  IY=C847
    -  PC=004F  A=B1  B=D8  CC: E F - I - Z - -
  >E 0000-004F
  - 0000  200C2E74 CBB10001 02030405 06070F03    ..t............
  - 0010  0F040F05 8E000D7E 003A9603 9702DC04  .......~.:......
  - 0020  58490902 58490902 DB059904 DD049602  XI..XI..........
  - 0030  99039703 08050904 0903A684 9B059705  ................
  - 0040  24060C04 26020C03 301F8C00 0626CB39  $...&...0....&.9
  >



Another view of it running at the bottom, so yes not run on a real 6809, but I even have a real one that I could probably get to run it.


 

Offline MIS42N

  • Frequent Contributor
  • **
  • Posts: 510
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #26 on: December 06, 2022, 07:12:12 am »
I have that downloaded and it is a handy app to test 68xx code fragments once you understand how it expects the code to be formatted.

Just tried it and seems to work like a champ. Thank you!
You are welcome. I didn't thoroughly test it. The add 1 byte to 3 bytes (label 'first') needs thrashing. I think it's OK, but this is the first bit of code I've written for 680x.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 3998
  • Country: nz
Re: Cleaning up a bit of 6800 assembly code
« Reply #27 on: December 06, 2022, 08:40:32 am »
So, I did what I thought of before - assembled it for 6809 and lo, it worked. I had to adjust the source to keep the assembler used happy, but the instructions are unchanged. At least, unchanged by me, the assembler did its usual thing of converting the DEX instruction (which 6809 does not have) into LEAX -1,X .
As I'm sure you are aware, they went to some trouble to make the 6809 source code compatible with the 6800, but the binary encodings are completely different.

As another example, the LDAA 0,X was implemented as LDA ,X with no offset at all. The 6809 can do 0, 5, 8 or 16 bit offsets from X, Y, S, or U. The 6800 can only do 8 bit offsets from X.
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3796
  • Country: gb
Re: Cleaning up a bit of 6800 assembly code
« Reply #28 on: December 06, 2022, 10:28:23 am »
THRSim11 is the best one for me

I have a couple of hc11 boards, I could attach to the internet, but I don't have the technology to redirect the serial monitor to a browser.

I have developed a downloader that resets the board before downloading a program, so it could also be possible to interface it to a browser in order to download a binary-file (s19) to the target.
« Last Edit: December 06, 2022, 10:51:44 am by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #29 on: December 06, 2022, 11:08:47 am »
So, I did what I thought of before - assembled it for 6809 and lo, it worked. I had to adjust the source to keep the assembler used happy, but the instructions are unchanged. At least, unchanged by me, the assembler did its usual thing of converting the DEX instruction (which 6809 does not have) into LEAX -1,X .
As I'm sure you are aware, they went to some trouble to make the 6809 source code compatible with the 6800, but the binary encodings are completely different.

As another example, the LDAA 0,X was implemented as LDA ,X with no offset at all. The 6809 can do 0, 5, 8 or 16 bit offsets from X, Y, S, or U. The 6800 can only do 8 bit offsets from X.

6809 opcodes are different, but I wouldn't call them completely different. Here is the same code assembled for 6800:


Code: [Select]

    1  0000 20 0C             BRA    CONVERT
    2                
    3  0002 00        TEMP5   FCB    0
    4                
    5  0003 00        BINV0   FCB    0         ; BIG ENDIAN
    6  0004 00        BINV1   FCB    0
    7  0005 00        BINV2   FCB    0
    8                
    9  0006 00        READ0   FCB    0         ; CHECKSUM BYTE
   10  0007 01                FCB    1         ; LITTLE ENDIAN VALUE
   11  0008 02                FCB    2         ; 7,654,321
   12  0009 03                FCB    3
   13  000A 04                FCB    4
   14  000B 05                FCB    5
   15  000C 06                FCB    6
   16  000D 07        READ7   FCB    7         ; FIRST DIGIT
   17                
   18  000E 7F 00 03  CONVERT CLR    BINV0     ; RESULT = 0
   19  0011 7F 00 04          CLR    BINV1
   20  0014 7F 00 05          CLR    BINV2
   21  0017 CE 00 0D          LDX    #READ7    ; POINT TO FIRST DIGIT
   22  001A 7E 00 44          JMP    FIRST
   23                
   24  001D 96 03     LOOP    LDA A  BINV0     ; MULTIPLY BINARY VALUE BY 10
   25  001F 97 02             STA A  TEMP5
   26  0021 01 01 01          LDD    BINV1     ; 2 SHIFTS = MULTIPLY BY 4
**   UNRECOGNIZABLE MNEMONIC
   27  0024 58                ASL B
   28  0025 49                ROL A
   29  0026 79 00 02          ROL    TEMP5
   30  0029 58                ASL B
   31  002A 49                ROL A
   32  002B 79 00 02          ROL    TEMP5
   33  002E DB 05             ADD B  BINV2     ; ADD THE ORIGINAL = MULTIPLY BY 5
   34  0030 99 04             ADC A  BINV1
   35  0032 01 01 01          STD    BINV1
**   UNRECOGNIZABLE MNEMONIC
   36  0035 96 02             LDA A  TEMP5
   37  0037 99 03             ADC A  BINV0
   38  0039 97 03             STA A  BINV0
   39  003B 78 00 05          ASL    BINV2     ; 1 SHIFT = MULTIPLY BY 10
   40  003E 79 00 04          ROL    BINV1
   41  0041 79 00 03          ROL    BINV0
   42                
   43  0044 A6 00     FIRST   LDA A  0,X       ; ADD IN NEXT DIGIT
   44  0046 9B 05             ADD A  BINV2
   45  0048 97 05             STA A  BINV2
   46  004A 24 08             BCC    NEXT
   47  004C 7C 00 04          INC    BINV1
   48  004F 26 03             BNE    NEXT
   49  0051 7C 00 03          INC    BINV0
   50  0054 09        NEXT    DEX
   51  0055 8C 00 06          CPX    #READ0    ; ALL DONE?
   52  0058 26 C3             BNE    LOOP
   53  005A 39                RTS


 

Assembled strictly for 6800, LDD and STD have quite rightly been rejected, but many of the assembled instructions, BRA, JMP, ASLA , ROLA, and more are identical. Other instructions like CLR BINV0 are only different because 6800 does not have a Direct addressing mode variant, while 6809 does have, and the 6809 opcode for CLR Extended is the same as for CLR Extended on 6800. But yes, there are many differences too.

6809 indexed addressing is very different to 6800. Besides the 0, 5, 8 and 16 bit offsets from X, Y, S or U, it also has register offset (A, B, or D) from X, Y, S or U, 0 offset from X, Y, S, or U with auto post-increment or pre-decrement by 1 or 2, 8 and 16 bit offsets from PC, and then a whole bunch of indirect indexed modes.
« Last Edit: December 06, 2022, 11:21:50 am by ozcar »
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3796
  • Country: gb
Re: Cleaning up a bit of 6800 assembly code
« Reply #30 on: December 06, 2022, 11:32:56 am »
Hc11 should have special x and y opcodes not implemented in 6800.
I remember something from an old project :-//
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline metertech58761Topic starter

  • Regular Contributor
  • *
  • Posts: 154
  • Country: us
Re: Cleaning up a bit of 6800 assembly code
« Reply #31 on: December 06, 2022, 01:06:25 pm »
The main reason the 6801 / HC11 instruction set was called for is that other parts of this code uses the D (combined A / B) register for certain bit-shift operations and the MUL opcode for one math section.

The code also has a routine that goes the other way, from binary to packed BCD (as well as a separate routine that unpacks BCD), but I want to get a better understanding of the arguments passed to the routine first before I ask for help picking apart that bit of code.
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #32 on: December 06, 2022, 11:17:12 pm »
The main reason the 6801 / HC11 instruction set was called for is that other parts of this code uses the D (combined A / B) register for certain bit-shift operations and the MUL opcode for one math section.

I note that the code in the original post for some reason used ASLD but not LDD/STD, while the code as proposed by MIS42N that I tried on 6809 uses LDD and STD, but not ASLD. So, using ASLD as well and I now have this (also rearranged a bit as I saw no reason for FIRST to be last):


Code: [Select]

   98  438A 7F 43 7C  CONVERT CLR    BINV0     ; RESULT = 0
   99  438D 7F 43 7D          CLR    BINV1
  100  4390 7F 43 7E          CLR    BINV2
  101  4393 CE 43 86          LDX    #READ7    ; SETUP FOR FIRST DIGIT
  102                
  103  4396 A6 00     LOOP    LDA A  0,X       ; NEXT DIGIT TO ADD IN
  104  4398 BB 43 7E          ADD A  BINV2
  105  439B B7 43 7E          STA A  BINV2
  106  439E 24 08             BCC    NEXT
  107  43A0 7C 43 7D          INC    BINV1
  108  43A3 26 03             BNE    NEXT
  109  43A5 7C 43 7C          INC    BINV0
  110  43A8 09        NEXT    DEX
  111  43A9 8C 43 7F          CPX    #READ0    ; ALL DONE?
  112  43AC 27 2B             BEQ    DONE      ; YES
  113                
  114  43AE B6 43 7C          LDA A  BINV0     ; MULTIPLY BINARY VALUE BY 10
  115  43B1 B7 43 7B          STA A  TEMP5
  116  43B4 FC 43 7D          LDD    BINV1     ; 2 SHIFTS = MULTIPLY BY 4
  117  43B7 05                ASL D
  118  43B8 79 43 7B          ROL    TEMP5
  119  43BB 05                ASL D
  120  43BC 79 43 7B          ROL    TEMP5
  121  43BF F3 43 7D          ADD D  BINV1     ; ADD THE ORIGINAL = MULTIPLY BY 5
  122  43C2 FD 43 7D          STD    BINV1
  123  43C5 B6 43 7B          LDA A  TEMP5
  124  43C8 B9 43 7C          ADC A  BINV0
  125  43CB B7 43 7C          STA A  BINV0
  126  43CE 78 43 7E          ASL    BINV2     ; 1 SHIFT = MULTIPLY BY 10
  127  43D1 79 43 7D          ROL    BINV1
  128  43D4 79 43 7C          ROL    BINV0
  129  43D7 20 BD             BRA    LOOP
  130                        
  131  43D9           DONE    EQU    *


For something a bit different, that was assembled for 6803, and tested on the pretend 6803 that I had to hand, which explains the somewhat weird address that was assembled for.

 
The following users thanked this post: MIS42N

Offline MIS42N

  • Frequent Contributor
  • **
  • Posts: 510
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #33 on: December 07, 2022, 08:26:40 am »
I note that the code in the original post for some reason used ASLD but not LDD/STD, while the code as proposed by MIS42N that I tried on 6809 uses LDD and STD, but not ASLD. So, using ASLD as well and I now have this (also rearranged a bit as I saw no reason for FIRST to be last):
I had not encountered the 6800 before. So I just did what worked in the emulator. No attempt to optimise further. I tried writing ASLD but what I wrote wasn't accepted. At the time I remember thinking there probably wasn't one, but it it is more likely a typo on my part. Mea culpa.
 

Offline MIS42N

  • Frequent Contributor
  • **
  • Posts: 510
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #34 on: December 08, 2022, 12:18:21 pm »
To get more familiarity with the 6800, I wrote a binary to packed decimal routine. Normally one would use the DAA instruction, but the emulator doesn't implement it. So in the emulator, the DAA instruction is emulated by a subroutine EmDAA. Two levels of emulation!

The subroutine EmDAA is a bit obscure, it was based on a table in the Motorola_M6800_Programming_Reference_Manual_M68PRM(D)_Nov76.pdf which I found online.

Code: [Select]
        bra convert

Pdec0   .byte 0       ; result
Pdec1   .byte 1       ; big endian
Pdec2   .byte 2       ; packed decimal
Pdec3   .byte 3

binV0 .byte $74       ; big endian
binV1 .byte $CB
binV2 .byte $B1

count   .byte 0

convert clr   Pdec0   ; result = 0
        clr   Pdec1
        clr   Pdec2
        clr   Pdec3
        ldaa  #24  ; bits to shift
        staa  count

loop1   asl   binV2   ; get hi bit of binary
        rol   binV1
        rol   binV0
        ldx   #binV0
loop2   dex
        ldaa  0,X
        adca  0,X
        bsr   EmDAA ; emulated DAA
        staa  0,X
        cpx   #Pdec0
        bne   loop2
        dec   count
        bne   loop1
        rts

; emulate the DAA instruction
EmDAA   tab
        tpa
        anda  #$20 ; isolate half carry
        bcs   EmCy
        bne   EmCnHy ; C clear H set
; C clear H clear
        tba
        anda  #$0F
        cmpa  #$0A
        bcs   xxx
EmCnHy  addb  #$06
xxx     cmpb  #$A0
        bcs   EmXCn
Em60    addb  #$60
EmXCy   tba
        sec
        rts
EmXCn   clc
        tba
        rts
; C set
EmCy    bne   EmCyHy ; C set H set
        tba
        anda  #$0F
        cmpa  #$0A
        bcs   Em60
EmCyHy  addb  #$06
        bra   Em60
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #35 on: December 09, 2022, 07:37:45 am »
To get more familiarity with the 6800, I wrote a binary to packed decimal routine. Normally one would use the DAA instruction, but the emulator doesn't implement it. So in the emulator, the DAA instruction is emulated by a subroutine EmDAA. Two levels of emulation!

The subroutine EmDAA is a bit obscure, it was based on a table in the Motorola_M6800_Programming_Reference_Manual_M68PRM(D)_Nov76.pdf which I found online.

Code: [Select]
        bra convert

Pdec0   .byte 0       ; result
Pdec1   .byte 1       ; big endian
Pdec2   .byte 2       ; packed decimal
Pdec3   .byte 3

binV0 .byte $74       ; big endian
binV1 .byte $CB
binV2 .byte $B1

count   .byte 0

convert clr   Pdec0   ; result = 0
        clr   Pdec1
        clr   Pdec2
        clr   Pdec3
        ldaa  #24  ; bits to shift
        staa  count

loop1   asl   binV2   ; get hi bit of binary
        rol   binV1
        rol   binV0
        ldx   #binV0
loop2   dex
        ldaa  0,X
        adca  0,X
        bsr   EmDAA ; emulated DAA
        staa  0,X
        cpx   #Pdec0
        bne   loop2
        dec   count
        bne   loop1
        rts

; emulate the DAA instruction
EmDAA   tab
        tpa
        anda  #$20 ; isolate half carry
        bcs   EmCy
        bne   EmCnHy ; C clear H set
; C clear H clear
        tba
        anda  #$0F
        cmpa  #$0A
        bcs   xxx
EmCnHy  addb  #$06
xxx     cmpb  #$A0
        bcs   EmXCn
Em60    addb  #$60
EmXCy   tba
        sec
        rts
EmXCn   clc
        tba
        rts
; C set
EmCy    bne   EmCyHy ; C set H set
        tba
        anda  #$0F
        cmpa  #$0A
        bcs   Em60
EmCyHy  addb  #$06
        bra   Em60

What sort of strange emulator implements the half-carry flag but not the DAA instruction?

Having discovered myself some three decades ago (!) that the DAA instruction is a bit tricky to emulate, I grabbed your EmDAA routine and subjected it to the DAA testing from Wolfgang Schwotzer's CPUTEST program. That is really for testing 6809 emulation (and I think I found it bundled with a 6809 emulator, but I'm not sure now exactly where it was now). However, I think the 6800 DAA and 6809 DAA should be the same. Edit, found it here: https://github.com/aladur/flexemu/blob/master/src/tools/cputest.txt .

That is not a total torture test, but it does test DAA for 16 different accumulator A values for all four combinations of H and C flags, so a total of 256 tests. It found a problem on the final test for H=0, C=0, with A=$FF (should result in A=$65, but instead got A=$05). It stops at that point, so maybe it would find other problems too.

But then maybe you don't need a completely accurate DAA emulation there - I did not get a chance to see how you use the DAA there, and maybe any differences don't matter for your purposes. One way to to give it a good thorough test would be to combine the binary->decimal and decimal->binary conversions, and check that you get the same value you started with. You could start at zero and just add one each time - could be a good speed test for the emulator too.
« Last Edit: December 09, 2022, 10:17:12 am by ozcar »
 
The following users thanked this post: MIS42N

Offline MIS42N

  • Frequent Contributor
  • **
  • Posts: 510
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #36 on: December 09, 2022, 10:48:49 am »
That is not a total torture test, but it does test DAA for 16 different accumulator A values for all four combinations of H and C flags, so a total of 256 tests. It found a problem on the final test for H=0, C=0, with A=$FF (should result in A=$65, but instead got A=$05). It stops at that point, so maybe it would find other problems too.

But then maybe you don't need a completely accurate DAA emulation there - I did not get a chance to see how you use the DAA there, and maybe any differences don't matter for your purposes. One way to to give it a good thorough test would be to combine the binary->decimal and decimal->binary conversions, and check that you get the same value you started with. You could start at zero and just add one each time - could be a good speed test for the emulator too.
An oversight on my part. It is caused when there is a half carry when $06 is added to B, and the high nibble of B was $Fx. You are right, it would not be encountered the way it is being used. The A values are (packed decimal value)*2 + carry from previous (if there is one). So the high nibble of B will be even, and a half carry will make it odd.

Can be fixed by changing

Code: [Select]
EmCnHy  addb  #$06
xxx     cmpb  #$A0
to
Code: [Select]
EmCnHy  addb  #$06
        bcs   Em60
xxx     cmpb  #$A0

So even if I had done the binary->decimal->binary it wouldn't have shown an error. It needs something like $77+$88 (both legit packed decimal numbers) which after DAA should be $65 + C. So it does need fixing if someone is relying on it.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6172
  • Country: fi
    • My home page and email address
Re: Cleaning up a bit of 6800 assembly code
« Reply #37 on: December 09, 2022, 12:00:38 pm »
Is there a reference that describes the individual operations exactly?

For example, I thought half carry (H) was defined as
   R := (val1 & 0x0F) OP (val2 & 0x0F)
   H := (R < 0) OR (R > 9)
where val1 and val2 are the operands, and OP is the arithmetic operation done on them.

Is there an exact reference for these?  Actually, the only ones I'm missing are the condition codes' exact rules, and the division and multiplication instructions.
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #38 on: December 09, 2022, 07:06:56 pm »
That is not a total torture test, but it does test DAA for 16 different accumulator A values for all four combinations of H and C flags, so a total of 256 tests. It found a problem on the final test for H=0, C=0, with A=$FF (should result in A=$65, but instead got A=$05). It stops at that point, so maybe it would find other problems too.

But then maybe you don't need a completely accurate DAA emulation there - I did not get a chance to see how you use the DAA there, and maybe any differences don't matter for your purposes. One way to to give it a good thorough test would be to combine the binary->decimal and decimal->binary conversions, and check that you get the same value you started with. You could start at zero and just add one each time - could be a good speed test for the emulator too.
An oversight on my part. It is caused when there is a half carry when $06 is added to B, and the high nibble of B was $Fx. You are right, it would not be encountered the way it is being used. The A values are (packed decimal value)*2 + carry from previous (if there is one). So the high nibble of B will be even, and a half carry will make it odd.

Can be fixed by changing

Code: [Select]
EmCnHy  addb  #$06
xxx     cmpb  #$A0
to
Code: [Select]
EmCnHy  addb  #$06
        bcs   Em60
xxx     cmpb  #$A0

So even if I had done the binary->decimal->binary it wouldn't have shown an error. It needs something like $77+$88 (both legit packed decimal numbers) which after DAA should be $65 + C. So it does need fixing if someone is relying on it.

I added the extra instruction, and now it sails through all the tests without complaining.

I just noticed my dodgy arithmetic above, it does a total of 64 DAA tests, not 256. 64 DAA tests should be enough for anybody?
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #39 on: December 09, 2022, 07:12:08 pm »
Is there a reference that describes the individual operations exactly?

For example, I thought half carry (H) was defined as
   R := (val1 & 0x0F) OP (val2 & 0x0F)
   H := (R < 0) OR (R > 9)
where val1 and val2 are the operands, and OP is the arithmetic operation done on them.

Is there an exact reference for these?  Actually, the only ones I'm missing are the condition codes' exact rules, and the division and multiplication instructions.

I never did much with HC11, and don't remember much about it other than it had MUL,  FDIV and IDIV instructions. For 6800, 6803 and 6809 at least I think the half-carry was only meant for addition. I happen to have a real, printed on paper, version of the 6809 reference manual lying here and from that it looks like H is set in a useful way only for 8-bit ADD and ADC instructions. For other instructions including 16-bit ADD, 8-bit or 16-bit SUB, and MUL, H is either "not affected" or "undefined".

My first 6809 emulation was written in 68000 assembly language. 68000 not having half-carry, for the 6809 add instructions that needed valid H, I just added the low nybbles separately and used bit 4 (0x10 position) of the result as H.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6172
  • Country: fi
    • My home page and email address
Re: Cleaning up a bit of 6800 assembly code
« Reply #40 on: December 10, 2022, 07:44:33 am »
For 6800, 6803 and 6809 at least I think the half-carry was only meant for addition.
D'oh!  You're right; that also applies to 68HC11 as well. :-+
 

Offline MIS42N

  • Frequent Contributor
  • **
  • Posts: 510
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #41 on: December 13, 2022, 12:42:39 am »
I was thinking I had used the Half Carry for something in the past, finally found it. It was an AtMega328P project, I was holding 12 * 16 bit values in register pairs. The 16 bits was split 4/12 and I needed to compare the 12 bit values with one in the register pair ZH/ZL. Usually that would mean ANDing off the high 4 bits. Fortunately the processor set the H bit on compares as well as arithmetic operations so this works:
Code: [Select]
cp      r0,ZL
cpc     r1,ZH
brhs    n2insR0
This would be really useful in the code for the emulated DAA instead of having to transfer the value to another register and AND $0F to get rid of the high bits. Why does the 6800 not do this on compares? Compares are usually implemented in the processor as an arithmetic operation, discarding the result and keeping the status. One would think more circuitry would be needed to set the H flag only on addition and not otherwise.
 

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 320
  • Country: au
Re: Cleaning up a bit of 6800 assembly code
« Reply #42 on: December 13, 2022, 03:35:30 am »
I was thinking I had used the Half Carry for something in the past, finally found it. It was an AtMega328P project, I was holding 12 * 16 bit values in register pairs. The 16 bits was split 4/12 and I needed to compare the 12 bit values with one in the register pair ZH/ZL. Usually that would mean ANDing off the high 4 bits. Fortunately the processor set the H bit on compares as well as arithmetic operations so this works:
Code: [Select]
cp      r0,ZL
cpc     r1,ZH
brhs    n2insR0
This would be really useful in the code for the emulated DAA instead of having to transfer the value to another register and AND $0F to get rid of the high bits. Why does the 6800 not do this on compares? Compares are usually implemented in the processor as an arithmetic operation, discarding the result and keeping the status. One would think more circuitry would be needed to set the H flag only on addition and not otherwise.

The 6800 reference manual says that H is "not affected" by compare and subtract instructions.  As for why, maybe because subtract and compare were implemented by negating the second operand and then adding, and they couldn't be bothered to sort out the half-borrow, but did not want it to be "undefined"?

Somewhat strangely, the 6809 reference manual that I have ("Original issue, March 1, 1981"), says that H is "undefined" for both 8-bit compare and 8-bit subtracts. That would make source code compatibility with 6800 a bit tricky, so I did a test, this time on a real 6809, and for the few values that I tested, H was actually "not affected", so as stated for 6800. Now if I tested with another 6809, or perhaps even the same 6809 tomorrow, maybe the results would be different, but I don't think that is very likely. But your guess is better than mine as to why they would say "undefined" in the fine manual if you could rely on it being "not affected".
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf