changeset 184:ef64e3f4e229 current

merge
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 30 Jul 2022 18:22:06 +0900
parents 0eb94a8e4d0d
children f8a3a2819e2b
files README.txt examples/ef09.asm examples_forth/kernel09.4 src/a09.c src/engine.c src/makerom.c src/monitor.asm src/monitor.lst src/monitor.s src/v09.c src/v09s.c
diffstat 11 files changed, 354 insertions(+), 345 deletions(-) [+]
line wrap: on
line diff
--- a/README.txt	Sat Jul 30 17:32:55 2022 +0900
+++ b/README.txt	Sat Jul 30 18:22:06 2022 +0900
@@ -170,11 +170,66 @@
 
 # differences from real 6809:
 
-ldd #$0fc9
-addb #$40
-adca #$00
+        ldd #$0fc9
+        addb #$40               ; $C9+$40 -> $09 -> C=1
+        adca #$00               ; $0F+C -> $10 -> H=1
+
+Should Set the half-carry!
+
+For this example the half-carry is set on a real 6809, also correctly
+emulated on the VCC. v09s does the same.
+
+According to "Motorola 6809 and Hitachi 6309 Programmer's Reference"
+the half-carry is only properly set for ADD and ADC (on 8-bit accumulators).
+For ASR, ASL (= LSL), CMP, SBC, SUB this condition flag is undefined.
+The v09s simulator calculates the half-carry also for ASR and ASL.
+
+ASL does the following:
+ * sets H if bit 4 was set.
+ * clears H if bit was not set.
+
+ASR (=LSR) does the following:
+ * xxx1 xxxx  --- (LSR|ASR) --->  xxxx 1xxx  => H=1
+ * xxx0 xxxx  --- (LSR|ASR) --->  xxxx 0xxx  => H=0
+
+
+But note: LSR never touches the half-carry!
+
+
+## TFR/EXG with unaligned register sizes
 
-H is set on VCC but not on real 6809, sim6809 does what?
+See http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=5512
+        Points to the 6309 behavior which is not compatible to 6809!
+
+tfr x,b         ; 6809,6309: b low byte of x, a unchanged
+tfr x,a         ; 6809, a low byte of x, b unchanged 
+		; on a 6309: a high(!) byte of x, b unchanged
+
+Might be used to get the low byte out of an index register without harm
+the A register:
+
+instead of
+        pushs a
+        tfr x,d
+        andb #$1f
+it could be used
+        tfr x,b
+        andb #$1f       ; a left untouched!
+
+REF: http://www.6809.org.uk/dragon/illegal-opcodes.shtml
+REF: http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4886
+
+tfr a,x         ; low byte of x has value of a, high byte is $FF
+tfr b,x         ; low byte of x has value of b, high byte is $FF
+
+exg a,x         ; low byte of x has value of a, high byte is $FF
+exg b,x         ; low byte of x has value of b, high byte is $FF
+
+According to Motorola 6809 and Hitachi 6309 Programmer's Reference
+
+Except for the case where the first operand is 8 bit and register CC or DP:
+In this case the 16-bit register has the value of the 8-bit register in
+high and low byte!
 
           
 ### special behavior
--- a/examples/ef09.asm	Sat Jul 30 17:32:55 2022 +0900
+++ b/examples/ef09.asm	Sat Jul 30 18:22:06 2022 +0900
@@ -109,7 +109,7 @@
 ; MUST BE IN SAME ORDER AS USER VARIABLES.
 
 
-UZERO		RMB     8			;reserved space in user area
+UZERO		FCB     0,0,0,0,0,0,0,0		;reserved space in user area
 		FDB	SPP			;SP0
 		FDB	RPP			;RP0
 		FDB	QRX			;'?KEY
@@ -130,7 +130,7 @@
 		FDB	0			;HLD
 		FDB	0			;HANDLER
 		FDB	0			;CONTEXT pointer
-		RMB     VOCSS*2			;vocabulary stack
+		FDB     0,0,0,0,0,0,0,0		;vocabulary stack (VOCSS*2 bytes)
 		FDB	0			;CURRENT pointer
 		FDB	0			;vocabulary link pointer
 		FDB	CTOP			;CP
--- a/examples_forth/kernel09.4	Sat Jul 30 17:32:55 2022 +0900
+++ b/examples_forth/kernel09.4	Sat Jul 30 18:22:06 2022 +0900
@@ -42,7 +42,7 @@
 
 LABEL DOCOL
  STU ,--Y \ Save IP on return stack.
- LDU ,S++ \ Pop IP from stack where it is left by JSR DOCOL.
+ PULS U \ Pop IP from stack where it is left by JSR DOCOL.
  NEXT
 
 LABEL DODEFER
@@ -51,8 +51,8 @@
 ENDASM
 
 CODE LIT ( --- n)
- LDD ,U++ \ Get literal from instruction stream.
- STD ,--S
+ PULU D \ Get literal from instruction stream.
+ PSHS D
  NEXT
 END-CODE
 
@@ -84,18 +84,18 @@
 END-CODE
 
 CODE (DO) ( l s ---)
- LDD  ,S++
+ PULS D
 LABEL DO1
  SUBD 0 ,S
  EORA # $80 \ Now START-LIMIT-$8000 Initial value for counter.
- LDX ,S++
+ PULS X
  STX ,--Y   \ Push limit value.
  STD ,--Y
  NEXT
 END-CODE
 
 CODE (?DO) ( l s ---)
- LDD ,S++
+ PULS D
  CMPD 0 ,S
  0<> IF
    LEAU 2 ,U \ Skip branch address.
@@ -143,13 +143,13 @@
  LDD 0 ,Y
  EORA # $80
  ADDD 2 ,Y
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
 CODE I' ( ---n)
  LDD 2 ,Y
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -157,7 +157,7 @@
  LDD 4 ,Y
  EORA # $80
  ADDD 6 ,Y
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -168,19 +168,19 @@
 
 CODE R@ ( --- n)
  LDD 0 ,Y
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
 CODE >R ( n ---)
- LDD ,S++
+ PULS D
  STD ,--Y
  NEXT
 END-CODE
 
 CODE R> ( --- n)
  LDD ,Y++
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -196,12 +196,12 @@
 
 CODE SP@ ( --- addr)
  TFR S, D
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
 CODE SP! ( addr ---)
- LDD ,S++
+ PULS D
  TFR D, S
  NEXT
 END-CODE
@@ -238,38 +238,34 @@
 END-CODE
 
 CODE UM/MOD  ( ud u --- rem quot)
- LEAS -1 ,S \ Create room for iteration counter.
- LDA # 16
- STA 0 ,S
+ LDX # 16 \ iteration counter.
+ LDD 2 ,S
  BEGIN
-  ASL 6 ,S
-  ROL 5 ,S
+  ASL 5 ,S
   ROL 4 ,S
-  ROL 3 ,S
-  LDD 3 ,S
+  ROLB
+  ROLA
   U< IF     \ Account for extra bit shifted out, perform subtraction anyway.
-   SUBD 1 ,S
-   STD 3 ,S
-   INC 6 ,S
+   SUBD 0 ,S
+   INC 5 ,S
   ELSE
-   SUBD 1 ,S  \ Perform trial subtraction.
+   CMPD 0 ,S  \ Perform trial subtraction.
    U>= IF
-    STD 3 ,S
-    INC 6 ,S  \ Add 1-bit to quotient.
+    SUBD 0 ,S
+    INC 5 ,S  \ Add 1-bit to quotient.
    THEN
   THEN
-  DEC 0 ,S
+  LEAX -1 ,X
   0= UNTIL
-  LEAS 3 ,S
-  LDD 2 ,S
-  LDX 0 ,S
-  STX 2 ,S
-  STD 0 ,S
+  LEAS 2 ,S
+  LDX 2 ,S  \ rem and quot on proper positions
+  STX 0 ,S
+  STD 2 ,S  \ D contains rem
   NEXT
 END-CODE
 
 CODE + ( n1 n2 ---n3)
- LDD  ,S++
+ PULS D
  ADDD 0 ,S
  STD 0 ,S
  NEXT
@@ -291,25 +287,25 @@
 END-CODE
 
 CODE AND ( n1 n2 ---n3)
- LDD 2 ,S
- ANDA ,S+
- ANDB ,S+
+ PULS D
+ ANDA ,S
+ ANDB 1 ,S
  STD 0 ,S
  NEXT
 END-CODE
 
 CODE OR ( n1 n2 ---n3)
- LDD 2 ,S
- ORA ,S+
- ORB ,S+
+ PULS D
+ ORA ,S
+ ORB 1 ,S
  STD 0 ,S
  NEXT
 END-CODE
 
 CODE XOR ( n1 n2 ---n3)
- LDD 2 ,S
- EORA ,S+
- EORB ,S+
+ PULS D
+ EORA ,S
+ EORB 1 ,S
  STD 0 ,S
  NEXT
 END-CODE
@@ -414,7 +410,7 @@
 
 CODE DUP   ( n --- n n )
  LDD 0 ,S
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -428,7 +424,7 @@
 
 CODE OVER  ( n1 n2 --- n1 n2 n1)
  LDD 2 ,S
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -485,9 +481,11 @@
 
 CODE PICK ( n1 --- n2)
  LDD 0 ,S
- ADDD ,S++
- LDD D,S
- STD ,--S
+ ADDD # 1 \ Correct index
+ ASLB     \ Cell* (assert: cellL=2!)
+ ROLA
+ LDX D,S  \ Pick value
+ STX 0 ,S \ Replace top
  NEXT
 END-CODE
 
@@ -555,7 +553,7 @@
  LDD 0 ,X
  LDX 2 ,X
  STX 0 ,S
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
@@ -776,12 +774,12 @@
 CODE KEY ( --- c)
  JSR 0
  CLRA
- STD ,--S
+ PSHS D
  NEXT
 END-CODE
 
 CODE EMIT ( c ---)
- LDD ,S++
+ PULS D
  JSR 3
  NEXT
 END-CODE
--- a/src/a09.c	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/a09.c	Sat Jul 30 18:22:06 2022 +0900
@@ -59,6 +59,16 @@
 #define FNLEN 30
 #define LINELEN 128
 
+
+/* forward declarations */
+
+
+void processfile(char *name);
+
+
+/* data structures */
+
+
 static int debug=0;
 static struct incl {
     char *name;
@@ -237,6 +247,8 @@
 
 void processfile(char *name);
 
+/* functions and procedures */
+
 struct oprecord * findop(char * nm)
 /* Find operation (mnemonic) in table using binary search */
 {
@@ -289,8 +301,7 @@
 char *listname,*objname,*srcname,*curname;
 int lineno,glineno;
 
-void
-outsymtable()
+void outsymtable()
 {
  int i,j=0;
  fprintf(listfile,"\nSYMBOL TABLE");
@@ -382,8 +393,7 @@
     error |= er ;
 }
 
-void
-scanname()
+void scanname()
 {
  int i=0;
  char c;
@@ -397,8 +407,7 @@
  srcptr--;
 }
 
-void
-skipspace()
+void skipspace()
 {
  char c;
  do {
@@ -678,14 +687,12 @@
  }
 }
 
-void
-set3()
+void set3()
 {
  if(mode<3)mode=3;
 }
 
-void
-scanspecial()
+void scanspecial()
 {
  set3();
  skipspace();
@@ -709,8 +716,7 @@
  }
 }
 
-void
-scanindexed()
+void scanindexed()
 {
  set3();
  postbyte=0;
@@ -744,8 +750,7 @@
 
 #define RESTORE {srcptr=oldsrcptr;c=*srcptr;goto dodefault;}
 
-void
-scanoperands()
+void scanoperands()
 {
  char c,d,*oldsrcptr;
  unknown=0;
@@ -866,9 +871,7 @@
   crc = -1;
 }
 
-
-void
-flushhex()
+void flushhex()
 {
  int i;
  if(hexcount){
@@ -882,16 +885,14 @@
  }
 }
 
-void
-outhex(unsigned char x) 
+void outhex(unsigned char x) 
 {
  if(hexcount==16)flushhex();
  hexbuffer[hexcount++]=x;
  chksum+=x;
 }
 
-void
-outbuffer()
+void outbuffer()
 {
  int i;
  for(i=0;i<codeptr;i++) {
@@ -910,8 +911,7 @@
                 "Illegal mnemonic"
                };
 
-void
-report()
+void report()
 {
  int i;
  fprintf(stderr,"File %s, line %d:%s\n",curname,lineno,srcline);
@@ -926,8 +926,7 @@
  errors++;
 }
 
-void
-outlist()
+void outlist()
 {
  int i;
  fprintf(listfile,"%04X: ",oldlc);
@@ -945,8 +944,7 @@
  }
 }
 
-void
-setlabel(struct symrecord * lp)
+void setlabel(struct symrecord * lp)
 {
  while (prevlp) {
      struct symrecord *l = prevlp;
@@ -966,21 +964,18 @@
  }
 }
 
-void
-putbyte(unsigned char b)
+void putbyte(unsigned char b)
 {
  codebuf[codeptr++]=b;
 }
 
-void
-putword(unsigned short w)
+void putword(unsigned short w)
 {
  codebuf[codeptr++]=w>>8;
  codebuf[codeptr++]=w&0x0ff;
 }
 
-void
-doaddress() /* assemble the right addressing bytes for an instruction */
+void doaddress() /* assemble the right addressing bytes for an instruction */
 {
  int offs;
  switch(mode) {
@@ -1009,20 +1004,17 @@
  }
 }
 
-void
-onebyte(int co)
+void onebyte(int co)
 {
  putbyte(co);
 }
 
-void
-twobyte(int co)
+void twobyte(int co)
 {
  putword(co);
 }
 
-void
-oneimm(int co)
+void oneimm(int co)
 {
  scanoperands();
  if(mode>=3)
@@ -1031,8 +1023,7 @@
  putbyte(operand);
 }
 
-void
-lea(int co)
+void lea(int co)
 {
  putbyte(co);
  scanoperands();
@@ -1046,8 +1037,7 @@
  doaddress();
 }
 
-void
-sbranch(int co)
+void sbranch(int co)
 {
  int offs;
  scanoperands();
@@ -1072,8 +1062,7 @@
  putbyte(offs);
 }
 
-void
-lbra(int co)
+void lbra(int co)
 {
  scanoperands();
  if(mode!=1&&mode!=2)seterror(2);
@@ -1081,8 +1070,7 @@
  putword(operand-loccounter-3);
 }
 
-void
-lbranch(int co)
+void lbranch(int co)
 {
  scanoperands();
  if(mode!=1&&mode!=2)seterror(2);
@@ -1090,8 +1078,7 @@
  putword(operand-loccounter-4);
 }
 
-void
-arith(int co)
+void arith(int co)
 {
  scanoperands();
  switch(mode) {
@@ -1103,8 +1090,7 @@
  doaddress();
 }
 
-void
-darith(int co)
+void darith(int co)
 {
  scanoperands();
  switch(mode) {
@@ -1116,8 +1102,7 @@
  doaddress();
 }
 
-void
-d2arith(int co)
+void d2arith(int co)
 {
  scanoperands();
  switch(mode) {
@@ -1129,8 +1114,7 @@
  doaddress();
 }
 
-void
-oneaddr(int co)
+void oneaddr(int co)
 {
  scanoperands();
  switch(mode) {
@@ -1142,8 +1126,7 @@
  doaddress();
 }
 
-void
-tfrexg(int co)
+void tfrexg(int co)
 {
  struct regrecord * p;
  putbyte(co);
@@ -1160,8 +1143,7 @@
  putbyte(postbyte);
 }
 
-void
-pshpul(int co)
+void pshpul(int co)
 {
  struct regrecord *p;
  putbyte(co);
@@ -1232,9 +1214,7 @@
  os9 = 0;
 }
 
-
-void
-pseudoop(int co,struct symrecord * lp)
+void pseudoop(int co,struct symrecord * lp)
 {
  int i;
  char c;
@@ -1430,8 +1410,7 @@
 }
 
 
-void
-processline()
+void processline()
 {
  struct symrecord * lp;
  struct oprecord * op;
@@ -1495,8 +1474,7 @@
  loccounter+=codeptr;
 }
 
-void
-suppressline()
+void suppressline()
 {
  struct oprecord * op;
  srcptr=srcline;
@@ -1520,8 +1498,7 @@
  }  
  if(pass==2&&listing)outlist(); } 
 
-void
-usage(char*nm)
+void usage(char*nm)
 {
   fprintf(stderr,"Usage: %s [-o objname] [-l listname] [-s srecord-file] srcname\n",nm);
   exit(2);
@@ -1540,9 +1517,7 @@
   return out;
 } 
 
-
-void
-getoptions(int c,char*v[])
+void getoptions(int c,char*v[])
 {
  int i=1;
  if(c==1)usage(v[0]);
@@ -1592,8 +1567,7 @@
  listing=(listname!=0);
 }
 
-void
-expandline()
+void expandline()
 {
  int i=0,j=0,k,j1;
  for(i=0;i<128&&j<128;i++)
@@ -1610,8 +1584,7 @@
 }
 
 
-void
-processfile(char *name)
+void processfile(char *name)
 {
  char *oldname;
  int oldno;
@@ -1666,8 +1639,7 @@
  curname=oldname;
 }
 
-int
-main(int argc,char *argv[])
+int main(int argc,char *argv[])
 {
  char c;
  getoptions(argc,argv);
--- a/src/engine.c	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/engine.c	Sat Jul 30 18:22:06 2022 +0900
@@ -25,6 +25,16 @@
    ACIA emulation at port $E000
 
    Note: BIG_ENDIAN option is no longer needed.
+
+   Implementation notes:
+     half-carry: 
+       According to Motorola 6809 and Hitachi 6309 Programmer's Reference
+       half-carry is not defined for ASL, but as an arithmetic operation the
+       flag behaves like an add operation where the operator is added to itself.
+
+       According to Motorola 6809 and Hitachi 6309 Programmer's Reference
+       LSR does not influence half-carry.
+
 */
 
 #include <stdio.h>
@@ -147,7 +157,10 @@
 #define SETNZ8(b) {if(b)CLZ else SEZ if(b&0x80)SEN else CLN}
 #define SETNZ16(b) {if(b)CLZ else SEZ if(b&0x8000)SEN else CLN}
 
-#define SETSTATUS(a,b,res) if((a^b^res)&0x10) SEH else CLH \
+#define SETSTATUS(a,b,res) if((a^b^res^(res>>1))&0x80)SEV else CLV \
+                           if(res&0x100)SEC else CLC SETNZ8((Byte)res)
+
+#define SETSTATUSH(a,b,res) if((a^b^res)&0x10) SEH else CLH \
                            if((a^b^res^(res>>1))&0x80)SEV else CLV \
                            if(res&0x100)SEC else CLC SETNZ8((Byte)res)
 
@@ -160,31 +173,44 @@
                      else{IMMWORD(tw) if(f)ipcreg+=tw;}
 #define NXORV  ((iccreg&0x08)^((iccreg&0x02)<<2))
 
-/* MAcros for setting/getting registers in TFR/EXG instructions */
+/* Macros for setting/getting registers in TFR/EXG instructions */
+/* see http://www.6809.org.uk/dragon/illegal-opcodes.shtml */
+/* 8 <-> 16, high byte is filled with $ff! */
 #define GETREG(val,reg) switch(reg) {\
                          case 0: val=GETDREG;break;\
                          case 1: val=ixreg;break;\
                          case 2: val=iyreg;break;\
-                    	 case 3: val=iureg;break;\
-                    	 case 4: val=isreg;break;\
-                    	 case 5: val=ipcreg;break;\
-                    	 case 8: val=iareg;break;\
-                    	 case 9: val=ibreg;break;\
-                    	 case 10: val=iccreg;break;\
-                    	 case 11: val=idpreg;break;}
+                         case 3: val=iureg;break;\
+                         case 4: val=isreg;break;\
+                         case 5: val=ipcreg;break;\
+                         case 6: val=0xffff;break;\
+                         case 7: val=0xffff;break;\
+                         case 8: val=iareg|0xff00;break;\
+                         case 9: val=ibreg|0xff00;break;\
+                         case 10: val=iccreg|(iccreg<<8);break;\
+                         case 11: val=idpreg|(idpreg<<8);break;\
+                         case 12: val=0xffff;break;\
+                         case 13: val=0xffff;break;\
+                         case 14: val=0xffff;break;\
+                         case 15: val=0xffff;break;}
 
 #define SETREG(val,reg) switch(reg) {\
-			 case 0: SETDREG(val) break;\
-			 case 1: ixreg=val;break;\
-			 case 2: iyreg=val;break;\
-			 case 3: iureg=val;break;\
-			 case 4: isreg=val;break;\
-			 case 5: ipcreg=val;break;\
-			 case 8: iareg=val;break;\
-			 case 9: ibreg=val;break;\
-			 case 10: iccreg=val;break;\
-			 case 11: idpreg=val;break;}
-
+                         case 0: SETDREG(val) break;\
+                         case 1: ixreg=val;break;\
+                         case 2: iyreg=val;break;\
+                         case 3: iureg=val;break;\
+                         case 4: isreg=val;break;\
+                         case 5: ipcreg=val;break;\
+                         case 6: val=0xffff;break;\
+                         case 7: val=0xffff;break;\
+                         case 8: iareg=val&0xff;break;\
+                         case 9: ibreg=val&0xff;break;\
+                         case 10: iccreg=val&0xff;break;\
+                         case 11: idpreg=val&0xff;break;\
+                         case 12: val=0xffff;break;\
+                         case 13: val=0xffff;break;\
+                         case 14: val=0xffff;break;\
+                         case 15: val=0xffff;break;}
 
 #define LOADAC(reg) reg=mem(eaddr);
 #define STOREAC(reg) SETBYTE(eaddr,reg);
@@ -605,9 +631,15 @@
    case 0x1B: break; /*ILLEGAL*/
    case 0x1C: /* ANDCC*/ IMMBYTE(tb) iccreg&=tb;break;
    case 0x1D: /* SEX */ tw=SIGNED(ibreg); SETNZ16(tw) SETDREG(tw) break;
-   case 0x1E: /* EXG */ IMMBYTE(tb) {Word t2;GETREG(tw,tb>>4) GETREG(t2,tb&15)
-                        SETREG(t2,tb>>4) SETREG(tw,tb&15) } break;
-   case 0x1F: /* TFR */ IMMBYTE(tb) GETREG(tw,tb>>4) SETREG(tw,tb&15) break;
+   case 0x1E: /* EXG */ IMMBYTE(tb) { Word t2;
+			GETREG(tw,tb>>4) GETREG(t2,tb&15)
+                        SETREG(t2,tb>>4) SETREG(tw,tb&15)
+			} 
+			break;
+   case 0x1F: /* TFR */ IMMBYTE(tb) 
+			GETREG(tw,tb>>4) 
+			SETREG(tw,tb&15) 
+			break;
    case 0x20: /* (L)BRA*/  BRANCH(1) break;
    case 0x21: /* (L)BRN*/  BRANCH(0) break;
    case 0x22: /* (L)BHI*/  BRANCH(!(iccreg&0x05)) break;
@@ -731,7 +763,7 @@
    case 0x43: /*COMA*/   tb=~iareg;SETNZ8(tb);SEC CLV
                              iareg=tb;break;
    case 0x44: /*LSRA*/  tb=iareg;if(tb&0x01)SEC else CLC
-                             if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb)
+                             tb>>=1;SETNZ8(tb)
                              iareg=tb;break;
    case 0x45: break;/* ILLEGAL*/
    case 0x46: /*RORA*/  tb=(iccreg&0x01)<<7;
@@ -743,7 +775,7 @@
                              if(tb&0x40)tb|=0x80;iareg=tb;SETNZ8(tb)
                              break;
    case 0x48: /*ASLA*/  tw=iareg<<1;
-                             SETSTATUS(iareg,iareg,tw)
+                             SETSTATUSH(iareg,iareg,tw)
                              iareg=tw;break;
    case 0x49: /*ROLA*/  tb=iareg;tw=iccreg&0x01;
                              if(tb&0x80)SEC else CLC
@@ -764,7 +796,7 @@
    case 0x53: /*COMB*/   tb=~ibreg;SETNZ8(tb);SEC CLV
                              ibreg=tb;break;
    case 0x54: /*LSRB*/  tb=ibreg;if(tb&0x01)SEC else CLC
-                             if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb)
+                             tb>>=1;SETNZ8(tb)
                              ibreg=tb;break;
    case 0x55: break;/* ILLEGAL*/
    case 0x56: /*RORB*/  tb=(iccreg&0x01)<<7;
@@ -772,11 +804,11 @@
                              ibreg=(ibreg>>1)+tb;SETNZ8(ibreg)
                        	     break;
    case 0x57: /*ASRB*/  tb=ibreg;if(tb&0x01)SEC else CLC
-                             if(tb&0x10)SEH else CLH tb>>=1;
+                             tb>>=1;
                              if(tb&0x40)tb|=0x80;ibreg=tb;SETNZ8(tb)
                              break;
    case 0x58: /*ASLB*/  tw=ibreg<<1;
-                             SETSTATUS(ibreg,ibreg,tw)
+                             SETSTATUSH(ibreg,ibreg,tw)
                              ibreg=tw;break;
    case 0x59: /*ROLB*/  tb=ibreg;tw=iccreg&0x01;
                              if(tb&0x80)SEC else CLC
--- a/src/makerom.c	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/makerom.c	Sat Jul 30 18:22:06 2022 +0900
@@ -12,8 +12,7 @@
 unsigned char mem[0x8000];
 char linebuf[130];
 
-void
-hexerr()
+void hexerr()
 {
  fprintf(stderr,"Illegal character in hex number\n");
  exit(1);
@@ -38,8 +37,7 @@
  return b;
 }
 
-int
-main()
+void main()
 {
  FILE *romfile;
  unsigned int i,length,addr;
--- a/src/monitor.asm	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/monitor.asm	Sat Jul 30 18:22:06 2022 +0900
@@ -1,4 +1,5 @@
 	;Buggy machine language monitor and rudimentary O.S. version 1.0
+	; 2022-01-11 Fix error handing in A command
 
 * Memory map of SBC
 * $0-$40 Zero page variables reserved by monitor and O.S.
@@ -302,7 +303,7 @@
 		jmp endirq
 		jmp xerrhand
 		jmp expr
-		jmp asmerrvec
+		jmp asmerr
 * And this one to the I/O vector table.
 osvectbl	jmp osgetc
 		jmp osputc
--- a/src/monitor.lst	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/monitor.lst	Sat Jul 30 18:22:06 2022 +0900
@@ -1,4 +1,5 @@
 0000:                           ;Buggy machine language monitor and rudimentary O.S. version 1.0
+0000:                           ; 2022-01-11 Fix error handing in A command
 0000:                   
 0000:                   * Memory map of SBC
 0000:                   * $0-$40 Zero page variables reserved by monitor and O.S.
@@ -302,7 +303,7 @@
 E52F: 7EE517                            jmp endirq
 E532: 7EEE4B                            jmp xerrhand
 E535: 7EF6F9                            jmp expr
-E538: 7E0298                            jmp asmerrvec
+E538: 7EFBBA                            jmp asmerr
 E53B:                   * And this one to the I/O vector table.
 E53B: 7EE45A            osvectbl        jmp osgetc
 E53E: 7EE471                            jmp osputc
--- a/src/monitor.s	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/monitor.s	Sat Jul 30 18:22:06 2022 +0900
@@ -17,7 +17,7 @@
 S113E50004393414E6809D093514390C2C26080C82
 S113E5102B26040C2A3B123BD32B10932B26FB39BE
 S113E5207EE5177EE5177EE50B7EE5167EE56A7EC1
-S113E530E5177EEE4B7EF6F97E02987EE45A7EE481
+S113E530E5177EEE4B7EF6F97EFBBA7EE45A7EE466
 S113E540717EE4807EE4E47EE4F57EE4657EED4461
 S113E5507EED677EED8C7EEDCF7EEDAC7EE51834EE
 S113E56010347FBE029BAF6A2007EC6A830001ED82
--- a/src/v09.c	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/v09.c	Sat Jul 30 18:22:06 2022 +0900
@@ -29,8 +29,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+
 #include <strings.h>
 #include <sys/stat.h>
+
 #include <string.h>
 
 #define engine extern
@@ -77,8 +79,7 @@
 }
 
 
-void 
-read_image()
+void read_image()
 {
  FILE *image;
  if((image=fopen(romfile,"rb"))==NULL) 
@@ -147,8 +148,7 @@
 
 #define CHECKARG if(i==argc)usage();else i++;
 
-int
-main(int argc,char *argv[])
+int main(int argc,char *argv[])
 {
  char *imagename=0;
  int i;
--- a/src/v09s.c	Sat Jul 30 17:32:55 2022 +0900
+++ b/src/v09s.c	Sat Jul 30 18:22:06 2022 +0900
@@ -51,6 +51,12 @@
                         http://www.6809.org.uk/dragon/illegal-opcodes.shtml
         2016-10-06 JK
                 Fixed: wrong cmpu cycles
+        2017-10-20 JK
+                Fixed: H flag only changed for add and adc.
+	2019-09-16 JK
+		Fixed: TFR/EXG 8 to 16 bit (especially CC/DP handling)
+		Fixed: CLV for 16-bit ST/LD
+
 */
 
 #include <stdio.h>
@@ -66,6 +72,8 @@
 
 void finish();
 
+void cr();
+
 static int fdump=0;
 
 
@@ -257,7 +265,7 @@
 {
  Word w;
  IMMWORD(w)
- char off[6];
+ char off[7];
  sprintf(off,"$%04x,",w);
  da_ops(off,dixreg[idx],4);
  return(*ixregs[idx])+w;
@@ -407,8 +415,7 @@
  }
 }
 
-void
-ill() /* illegal opcode==noop */
+void ill() /* illegal opcode==noop */
 {
 }
 
@@ -428,12 +435,15 @@
 #define SETNZ8(b) {if(b)CLZ else SEZ if(b&0x80)SEN else CLN}
 #define SETNZ16(b) {if(b)CLZ else SEZ if(b&0x8000)SEN else CLN}
 
-#define SETSTATUS(a,b,res) if((a^b^res)&0x10) SEH else CLH \
+
+#define SETSTATUS(a,b,res) if((a^b^res^(res>>1))&0x80)SEV else CLV \
+                           if(res&0x100)SEC else CLC SETNZ8((Byte)res)
+
+#define SETSTATUS_H(a,b,res) if((a^b^res)&0x10) SEH else CLH \
                            if((a^b^res^(res>>1))&0x80)SEV else CLV \
                            if(res&0x100)SEC else CLC SETNZ8((Byte)res)
 
-void
-add()
+void add()
 {
  Word aop,bop,res;
  Byte* aaop;
@@ -442,12 +452,11 @@
  aop=*aaop;
  bop=mem[eaddr8()];
  res=aop+bop;
- SETSTATUS(aop,bop,res)
+ SETSTATUS_H(aop,bop,res)
  *aaop=res;
 }
 
-void
-sbc()
+void sbc()
 {
  Word aop,bop,res;
  Byte* aaop;
@@ -460,8 +469,7 @@
  *aaop=res;
 }
 
-void
-sub()
+void sub()
 {
  Word aop,bop,res;
  Byte* aaop;
@@ -474,8 +482,7 @@
  *aaop=res;
 }
 
-void
-adc()
+void adc()
 {
  Word aop,bop,res;
  Byte* aaop;
@@ -484,12 +491,11 @@
  aop=*aaop;
  bop=mem[eaddr8()];
  res=aop+bop+(ccreg&0x01);
- SETSTATUS(aop,bop,res)
+ SETSTATUS_H(aop,bop,res)
  *aaop=res;
 }
 
-void
-cmp()
+void cmp()
 {
  Word aop,bop,res;
  Byte* aaop;
@@ -501,8 +507,7 @@
  SETSTATUS(aop,bop,res)
 }
 
-void
-and()
+void and()
 {
  Byte aop,bop,res;
  Byte* aaop;
@@ -516,8 +521,7 @@
  *aaop=res;
 }
 
-void
-or()
+void or()
 {
  Byte aop,bop,res;
  Byte* aaop;
@@ -531,8 +535,7 @@
  *aaop=res;
 }
 
-void
-eor()
+void eor()
 {
  Byte aop,bop,res;
  Byte* aaop;
@@ -546,8 +549,7 @@
  *aaop=res;
 }
 
-void
-bit()
+void bit()
 {
  Byte aop,bop,res;
  Byte* aaop;
@@ -560,8 +562,7 @@
  CLV
 }
 
-void
-ld()
+void ld()
 {
  Byte res;
  Byte* aaop;
@@ -573,8 +574,7 @@
  *aaop=res;
 }
 
-void
-st()
+void st()
 {
  Byte res;
  Byte* aaop;
@@ -586,8 +586,7 @@
  CLV
 }
 
-void
-jsr()
+void jsr()
 {
  Word w;
 
@@ -599,8 +598,7 @@
  pcreg=w;
 }
 
-void
-bsr()
+void bsr()
 {
  Byte b;
  char off[6];
@@ -614,8 +612,7 @@
  da_ops(off,NULL,0);
 }
 
-void
-neg()
+void neg()
 {
  Byte *ea;
  Word a,r;
@@ -629,8 +626,7 @@
  *ea=r;
 }
 
-void
-com()
+void com()
 {
  Byte *ea;
  Byte r;
@@ -649,8 +645,7 @@
  *ea=r;
 }
 
-void
-lsr()
+void lsr()
 {
  Byte *ea;
  Byte r;
@@ -659,14 +654,15 @@
  ea=eaddr0();
  r=*ea;
  if(r&0x01)SEC else CLC
- if(r&0x10)SEH else CLH
+ /* according to Motorola 6809 and Hitachi 6309 Programmer's Reference
+  * half-carry is not changed
+  */
  r>>=1;
  SETNZ8(r)
  *ea=r;
 }
 
-void
-ror()
+void ror()
 {
  Byte *ea;
  Byte r,c;
@@ -681,8 +677,7 @@
  *ea=r;
 }
 
-void
-asr()
+void asr()
 {
  Byte *ea;
  Byte r;
@@ -698,8 +693,7 @@
  *ea=r;
 }
 
-void
-asl()
+void asl()
 {
  Byte *ea;
  Word a,r;
@@ -708,12 +702,16 @@
  ea=eaddr0();
  a=*ea;
  r=a<<1;
- SETSTATUS(a,a,r)
+ /* according to Motorola 6809 and Hitachi 6309 Programmer's Reference
+  * half-carry is not defined, but for an arithmetic operation the
+  * flag behaves like an add operation where the operator is added to
+  * itself.
+  */
+ SETSTATUS_H(a,a,r)
  *ea=r;
 }
 
-void
-rol()
+void rol()
 {
  Byte *ea;
  Byte r,c;
@@ -729,8 +727,7 @@
  *ea=r;
 }
 
-void
-inc()
+void inc()
 {
  Byte *ea;
  Byte r;
@@ -744,8 +741,7 @@
  *ea=r;
 }
 
-void
-dec()
+void dec()
 {
  Byte *ea;
  Byte r;
@@ -759,8 +755,7 @@
  *ea=r;
 }
 
-void
-tst()
+void tst()
 {
  Byte r;
  Byte *ea;
@@ -772,8 +767,7 @@
  CLV
 }
 
-void
-jmp()
+void jmp()
 {
  Byte *ea;
 
@@ -784,8 +778,7 @@
  pcreg=ea-mem;
 }
 
-void
-clr()
+void clr()
 {
  Byte *ea;
 
@@ -796,8 +789,7 @@
 
 extern void (*instrtable[])();
 
-void
-flag0()
+void flag0()
 {
  if(iflag) /* in case flag already set by previous flag instr don't recurse */
  {
@@ -811,8 +803,7 @@
  iflag=0;
 }
 
-void
-flag1()
+void flag1()
 {
  if(iflag) /* in case flag already set by previous flag instr don't recurse */
  {
@@ -826,26 +817,22 @@
  iflag=0;
 }
 
-void
-nop()
+void nop()
 {
  da_inst("nop",NULL,2);
 }
 
-void
-sync_inst()
+void sync_inst()
 {
  finish();
 }
 
-void
-cwai()
+void cwai()
 {
  sync_inst();
 }
 
-void
-lbra()
+void lbra()
 {
  Word w;
  char off[6];
@@ -858,8 +845,7 @@
  da_ops(off,NULL,0);
 }
 
-void
-lbsr()
+void lbsr()
 {
  Word w;
  char off[6];
@@ -873,8 +859,7 @@
  da_ops(off,NULL,0);
 }
 
-void
-daa()
+void daa()
 {
  Word a;
  da_inst("daa",NULL,2);
@@ -887,8 +872,7 @@
  *areg=a;
 }
 
-void
-orcc()
+void orcc()
 {
  Byte b;
  char off[7];
@@ -899,8 +883,7 @@
  ccreg|=b;
 }
 
-void
-andcc()
+void andcc()
 {
  Byte b;
  char off[6];
@@ -912,8 +895,7 @@
  ccreg&=b;
 }
 
-void
-mul()
+void mul()
 {
  Word w;
  w=*areg * *breg;
@@ -923,8 +905,7 @@
  *dreg=w;
 }
 
-void
-sex()
+void sex()
 {
  Word w;
  da_inst("sex",NULL,2);
@@ -933,23 +914,20 @@
  *dreg=w;
 }
 
-void
-abx()
+void abx()
 {
  da_inst("abx",NULL,3);
  xreg += *breg;
 }
 
-void
-rts()
+void rts()
 {
  da_inst("rts",NULL,5);
  da_len = 1;
  PULLWORD(pcreg)
 }
 
-void
-rti()
+void rti()
 {
  Byte x;
  x=ccreg&0x80;
@@ -968,8 +946,7 @@
  PULLWORD(pcreg)
 }
 
-void
-swi()
+void swi()
 {
  int w;
  da_inst("swi",(iflag==1)?"2":(iflag==2)?"3":"",5);
@@ -1007,23 +984,26 @@
 Byte *byteregs[]={d_reg+1,d_reg,&ccreg,&dpreg,&fillreg,&fillreg,&fillreg,&fillreg};
 #endif
 
-void
-tfr()
+void tfr()
 {
  Byte b;
  da_inst("tfr",NULL,7);
  IMMBYTE(b)
  da_reg(b);
  Word v;
+ // see http://www.6809.org.uk/dragon/illegal-opcodes.shtml
  // source in higher nibble (highest bit set means 8 bit reg.)
  if(b&0x80) {
-  v=*byteregs[(b&0x70)>>4] | (b&0x08 ? 0 : 0xff00);
+  v=*byteregs[(b&0x70)>>4] | 0xff00;
+  if ((b &0x70) == 0x20 || (b &0x70) == 0x30) { /* source is CC or DP */
+   v = (v & 0xff) << 8 | (v & 0xff); /* high byte is the same as the low byte */
+  }
  } else {
   v=*wordregs[(b&0x70)>>4];
  }
  // dest in lower nibble (highest bit set means 8 bit reg.)
  if(b&0x8) {
-  *byteregs[b&0x07]=v&0xff;
+  *byteregs[b&0x07]=v &0xff;
   fillreg=0xff;  // keep fillvalue
  } else {
   *wordregs[b&0x07]=v;
@@ -1031,17 +1011,21 @@
  }
 }
 
-void
-exg()
+void exg()
 {
  Byte b;
  Word f;
  Word t;
  da_inst("exg",NULL,8);
+ // see http://www.6809.org.uk/dragon/illegal-opcodes.shtml
+ // 8 <-> 16, high byte is filled with $ff!
  IMMBYTE(b)
  da_reg(b);
  if(b&0x80) {
   f=*byteregs[(b&0x70)>>4] | 0xff00;
+  if ((b &0x70) == 0x20 || (b &0x70) == 0x30) { /* first operand is CC or DP */
+   f = (f & 0xff) << 8 | (f & 0xff); /* high byte is the same as the low byte */
+  }
  } else {
   f=*wordregs[(b>>4)&0x07];
  }
@@ -1066,8 +1050,7 @@
  }
 }
 
-void
-br(int f)
+void br(int f)
 {
  Byte b;
  Word w;
@@ -1091,120 +1074,103 @@
 
 #define NXORV  ((ccreg&0x08)^(ccreg&0x02))
 
-void
-bra()
+void bra()
 {
  da_inst(iflag?"l":"","bra",iflag?5:3);
  br(1);
 }
 
-void
-brn()
+void brn()
 {
  da_inst(iflag?"l":"","brn",iflag?5:3);
  br(0);
 }
 
-void
-bhi()
+void bhi()
 {
  da_inst(iflag?"l":"","bhi",iflag?5:3);
  br(!(ccreg&0x05));
 }
 
-void
-bls()
+void bls()
 {
  da_inst(iflag?"l":"","bls",iflag?5:3);
  br(ccreg&0x05);
 }
 
-void
-bcc()
+void bcc()
 {
  da_inst(iflag?"l":"","bcc",iflag?5:3);
  br(!(ccreg&0x01));
 }
 
-void
-bcs()
+void bcs()
 {
  da_inst(iflag?"l":"","bcs",iflag?5:3);
  br(ccreg&0x01);
 }
 
-void
-bne()
+void bne()
 {
  da_inst(iflag?"l":"","bne",iflag?5:3);
  br(!(ccreg&0x04));
 }
 
-void
-beq()
+void beq()
 {
  da_inst(iflag?"l":"","beq",iflag?5:3);
  br(ccreg&0x04);
 }
 
-void
-bvc()
+void bvc()
 {
  da_inst(iflag?"l":"","bvc",iflag?5:3);
  br(!(ccreg&0x02));
 }
 
-void
-bvs()
+void bvs()
 {
  da_inst(iflag?"l":"","bvs",iflag?5:3);
  br(ccreg&0x02);
 }
 
-void
-bpl()
+void bpl()
 {
  da_inst(iflag?"l":"","bpl",iflag?5:3);
  br(!(ccreg&0x08));
 }
 
-void
-bmi()
+void bmi()
 {
  da_inst(iflag?"l":"","bmi",iflag?5:3);
  br(ccreg&0x08);
 }
 
-void
-bge()
+void bge()
 {
  da_inst(iflag?"l":"","bge",iflag?5:3);
  br(!NXORV);
 }
 
-void
-blt()
+void blt()
 {
  da_inst(iflag?"l":"","blt",iflag?5:3);
  br(NXORV);
 }
 
-void
-bgt()
+void bgt()
 {
  da_inst(iflag?"l":"","bgt",iflag?5:3);
  br(!(NXORV||ccreg&0x04));
 }
 
-void
-ble()
+void ble()
 {
  da_inst(iflag?"l":"","ble",iflag?5:3);
  br(NXORV||ccreg&0x04);
 }
 
-void
-leax()
+void leax()
 {
  Word w;
  da_inst("leax",NULL,4);
@@ -1213,8 +1179,7 @@
  xreg=w;
 }
 
-void
-leay()
+void leay()
 {
  Word w;
  da_inst("leay",NULL,4);
@@ -1223,15 +1188,13 @@
  yreg=w;
 }
 
-void
-leau()
+void leau()
 {
  da_inst("leau",NULL,4);
  ureg=postbyte();
 }
 
-void
-leas()
+void leas()
 {
  da_inst("leas",NULL,4);
  sreg=postbyte();
@@ -1256,8 +1219,7 @@
 }
 
 
-void
-pshs()
+void pshs()
 {
  Byte b;
  IMMBYTE(b)
@@ -1273,8 +1235,7 @@
  if(b&0x01)PUSHBYTE(ccreg)
 }
 
-void
-puls()
+void puls()
 {
  Byte b;
  IMMBYTE(b)
@@ -1291,8 +1252,7 @@
  if(b&0x80)PULLWORD(pcreg)
 }
 
-void
-pshu()
+void pshu()
 {
  Byte b;
  IMMBYTE(b)
@@ -1308,8 +1268,7 @@
  if(b&0x01)PUSHUBYTE(ccreg)
 }
 
-void
-pulu()
+void pulu()
 {
  Byte b;
  IMMBYTE(b)
@@ -1330,8 +1289,7 @@
                             if(((res>>1)^a^b^res)&0x8000) SEV else CLV \
                             SETNZ16((Word)res)}
 
-void
-addd()
+void addd()
 {
  unsigned long aop,bop,res;
  Word ea;
@@ -1344,8 +1302,7 @@
  *dreg=res;
 }
 
-void
-subd()
+void subd()
 {
  unsigned long aop,bop,res;
  Word ea;
@@ -1369,8 +1326,7 @@
  if(iflag==0) *dreg=res; /* subd result */
 }
 
-void
-cmpx()
+void cmpx()
 {
  unsigned long aop,bop,res;
  Word ea;
@@ -1393,19 +1349,18 @@
  SETSTATUSD(aop,bop,res)
 }
 
-void
-ldd()
+void ldd()
 {
  Word ea,w;
  da_inst("ldd",NULL,4);
  ea=eaddr16();
  w=GETWORD(ea);
  SETNZ16(w)
+ CLV
  *dreg=w;
 }
 
-void
-ldx()
+void ldx()
 {
  Word ea,w;
  if (iflag) da_inst("ldy",NULL,4);
@@ -1413,11 +1368,11 @@
  ea=eaddr16();
  w=GETWORD(ea);
  SETNZ16(w)
+ CLV
  if (iflag==0) xreg=w; else yreg=w;
 }
 
-void
-ldu()
+void ldu()
 {
  Word ea,w;
  if (iflag) da_inst("lds",NULL,4);
@@ -1425,22 +1380,22 @@
  ea=eaddr16();
  w=GETWORD(ea);
  SETNZ16(w)
+ CLV
  if (iflag==0) ureg=w; else sreg=w;
 }
 
-void
-std()
+void std()
 {
  Word ea,w;
  da_inst("std",NULL,4);
  ea=eaddr16();
  w=*dreg;
  SETNZ16(w)
+ CLV
  SETWORD(ea,w)
 }
 
-void
-stx()
+void stx()
 {
  Word ea,w;
  if (iflag) da_inst("sty",NULL,4);
@@ -1448,11 +1403,11 @@
  ea=eaddr16();
  if (iflag==0) w=xreg; else w=yreg;
  SETNZ16(w)
+ CLV
  SETWORD(ea,w)
 }
 
-void
-stu()
+void stu()
 {
  Word ea,w;
  if (iflag) da_inst("sts",NULL,4);
@@ -1460,6 +1415,7 @@
  ea=eaddr16();
  if (iflag==0) w=ureg; else w=sreg;
  SETNZ16(w)
+ CLV
  SETWORD(ea,w)
 }
 
@@ -1498,8 +1454,7 @@
 eor , adc ,  or , add , ldd , std , ldu , stu ,
 };
 
-void
-read_image(char* name)
+void read_image(char* name)
 {
  FILE *image;
  if((image=fopen(name,"rb"))!=NULL) {
@@ -1507,9 +1462,7 @@
   fclose(image);
  }
 }
-
-void
-dump()
+void dump()
 {
  FILE *image;
  if((image=fopen("dump.v09","wb"))!=NULL) {
@@ -1598,8 +1551,7 @@
 
 static char optstring[]="d";
 
-int
-main(int argc,char *argv[])
+int main(int argc,char *argv[])
 {
  char c;
  int a;
@@ -1661,7 +1613,7 @@
   trace();
 #endif
 
- pcreg_prev = pcreg;
+  pcreg_prev = pcreg;
 
  } /* for */
  return 0;