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
>
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!
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 .
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.
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
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.
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 *
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):
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
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
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.
EmCnHy addb #$06
xxx cmpb #$A0
toEmCnHy addb #$06
bcs Em60
xxx cmpb #$A0
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 changingCode: [Select]EmCnHy addb #$06
to
xxx cmpb #$A0Code: [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.
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.
For 6800, 6803 and 6809 at least I think the half-carry was only meant for addition.
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.
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
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.
cpc r1,ZH
brhs n2insR0