Kowalski Simulator Updates

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Kowalski Simulator Updates

Post by BigDumbDinosaur »

BTW, I finally got around to fiddling with the .PARAMTYPE() macro qualifier.  If I assemble the nonsense code...

Code: Select all

enum     .macro ...
.pt      = .PARAMTYPE(@1)
         .endm
;
         *=0
;
         enum "123"            ;invoke macro with a string

...the local symbol .pt will be set to 2, indicating the argument to the macro invocation is a character string.

Code: Select all

enum     .macro ...
.pt      = .PARAMTYPE(@1)
         .endm
;
         *=0
;
         enum 123              ;invoke macro with a number

The above will set .pt to 1, indicating the argument to be numeric.

A reason I am looking at .PARAMTYPE() is I have been trying to create a macro that is an analog of C’s enum.  My enum would be invoked as...

Code: Select all

         enum "a1","a2","a3"

...with a variable number of arguments, minimum of 2.  The idea is enum would loop over the arguments and execute a1 = 0, a2 = 1, a3 = 2, etc., for how many arguments were passed.

So I concocted the following...

Code: Select all

enum     .macro ...
         .if @0 < 2                    ;number of args
           .error ""+@0$+": 2 or more args must be specified"
         .endif
.e       .set 0                        ;enumeration index (0,1,2 ...)
         .rept @0                      ;repeat for each arg
           .if .paramtype(@{.e+1})==2  ;if arg is a string...
@{.e+1}$     = .e                      ;enumerate it <—— won’t work
.e           .= .e+1                   ;enum index ++
           .else
             .error ""+@0$+": arguments must be strings"
           .endif
         .endr
         .endm

Unfortunately, the above won’t work, the sticking point being the line highlighted with the left-arrow.  You’d think that parsing of the arguments would insert, for example, "a1 = .e" into the code flow, setting a1 to whatever .e happens to be.  Evidently, @{.e+1}$ does not get expanded to whatever that particular argument holds, resulting in error.

The general takeaway is there is no way to dynamically define global symbols in a macro.  So much for my enum macro.  :cry:
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Kowalski Simulator Updates

Post by GARTHWILSON »

That is a neat idea though!
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Kowalski Simulator Updates

Post by BigDumbDinosaur »

GARTHWILSON wrote:
That is a neat idea though!
Thanks!  Sometimes I manage to fool humans with my smarts routine.  :D

Based upon on the K&R C “white book,” enum has been part of the language almost since inception (over 50 years ago!).  There are any number of instances in assembly language in which an enumerated progression is useful, e.g.:

Code: Select all

e_okay   =$00                  ;no/non-specific error
e_memf   =$01                  ;memory fault
e_rtcf   =$02                  ;RTC fault
e_nvrf   =$03                  ;NVRAM fault
e_sscf   =$04                  ;SCSI HBA general fault
e_sscfe  =$05                  ;SCSI HBA FIFO fault

In my programs, I don’t embed “magic numbers” such as an error codes in program statements—I only use symbols.  So being able to abstract the above error codes with an enum function would very useful, e.g....

Code: Select all

         enum 0,e_okay,e_memf,e_rtcf,e_nvrf,e_sscf,e_sscfe

...instead of making a bunch of line-by-line assignments, which is vulnerable to entry errors.

The 0 immediately following enum is the starting index, which would result in e_okay being set to $00.  If it had been 10, e_okay would be $0A, e_memf would be $0B, and so on.

Another place where an enum function would be useful would be in defining exit codes that are local to a function, e.g....

Code: Select all

;	—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
;	Error Codes (description order)
;	—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
;
ec_buffr =0                    ;buffer overrun
ec_prend =1                    ;premature load end
ec_ivtyp =2                    ;undefined record type
ec_uityp =3                    ;unimplemented record type
ec_lngth =4                    ;invalid data length
ec_corup =5                    ;corrupted record
ec_cksum =6                    ;checksum mismatch
ec_maxer =7                    ;too many session errors
ec_abort =8                    ;user abort
;
;	—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
;	Record Loading Exception Codes
;	—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
;
el_abort =0                    ;user aborted
el_eot   =1                    ;end of transmission
el_buf   =2                    ;buffer overrun

The above are defined in my new-and-improved S-record loader that is currently in development.  It would have been much less typing if I could do...

Code: Select all

         enum 0,ec_buffr,ec_prend,ec_ivtyp,ec_uityp,ec_lngth,ec_corup,ec_cksum,ec_maxer,ec_abort
         enum 0,el_abort,el_eot,el_buf

Assuming my enum macro is written as follows...

Code: Select all

enum     .macro ...                    ;enum 0,"a1","a2","a3"...
         .if @0 > 1
.np        = @0-1                      ;args to enumerate
.e         .set @1                     ;starting enumeration index
.i         .set 1                      ;arg index
           .rept .np                   ;repeat for number of args
             .if .paramtype(@.i) == 2  ;if arg is a string...
@.i$           = .e                    ;enumerate it <——
.e             .= .e+1                 ;bump enum index
.i             .= .i+1                 ;bump arg idnex
             .else
               .error ""+@0$+": arguments must be strings."
             .endif
           .endr
         .else
           .error "usage: "+@0$+"index,parm1 [,parm2 [,...]]"
         .endif
         .endm

...saying...

Code: Select all

         enum 5,ec_buffr,ec_prend,ec_ivtyp,ec_uityp,ec_lngth,ec_corup,ec_cksum,ec_maxer,ec_abort

...would make ec_buffr = 5, ec_prend = 6, and so on.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Re: Kowalski Simulator Updates

Post by teamtempest »

Quote:
Code:
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
; Error Codes (description order)
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
;
ec_buffr =0 ;buffer overrun
ec_prend =1 ;premature load end
ec_ivtyp =2 ;undefined record type
ec_uityp =3 ;unimplemented record type
ec_lngth =4 ;invalid data length
ec_corup =5 ;corrupted record
ec_cksum =6 ;checksum mismatch
ec_maxer =7 ;too many session errors
ec_abort =8 ;user abort
;
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
; Record Loading Exception Codes
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
;
el_abort =0 ;user aborted
el_eot =1 ;end of transmission
el_buf =2 ;buffer overrun

The above are defined in my new-and-improved™ S-record loader that is currently in development. It would have been much less typing if I could do...

Code:
enum 0,ec_buffr,ec_prend,ec_ivtyp,ec_uityp,ec_lngth,ec_corup,ec_cksum,ec_maxer,ec_abort
enum 0,el_abort,el_eot,el_buf
Forgive me, but while I can see what you're trying to do, my opinion is that the first form (the one you're trying to get away from) is much more readable and understandable than the second. The first form explicitly says what each error code means, but in the second it's completely opaque what "ec_maxer" (for instance) means. Just looking at it, my first assumption would be that it's some value that can't be exceeded, but my second would be that it's the last possible error code value as well (and it isn't).

But I understand wanting to get away from hard-coded error numbers. Perhaps another approach would be to scale back a bit such a macro. Maybe make two macros, one to set the initial value and another to assign each value. I don't know details of how Kowalski macros work, but perhaps something like this (I'm assuming "set" means assigning a value that can later be changed):

enum .macro ...
.if @0 > 0
.e .set @1
.else
.e .set 0
.endif
.endm

next .macro
@1 .set .e
.e .= .e + 1
.endm

and then, for example:

; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
; Error Codes (description order)
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
;
enum
next ec_buffr ;buffer overrun
next ec_prend ;premature load end
next ec_ivtyp ;undefined record type
next ec_uityp ;unimplemented record type
next ec_lngth ;invalid data length
next ec_corup ;corrupted record
next ec_cksum ;checksum mismatch
next ec_maxer ;too many session errors
next ec_abort ;user abort
;
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
; Record Loading Exception Codes
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
;
enum
next el_abort ;user aborted
next el_eot ;end of transmission
next el_buf ;buffer overrun

Although, hmm, it might be possible to get away with only one "enum" macro. If no argument, start counting at zero, if a numeric argument, start counting there, if a string argument, assign the current count value to it...
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Kowalski Simulator Updates

Post by BigDumbDinosaur »

teamtempest wrote:
Although, hmm, it might be possible to get away with only one "enum" macro. If no argument, start counting at zero, if a numeric argument, start counting there, if a string argument, assign the current count value to it...

The macro I presented in my previous post more-or-less does that.  The first argument is the starting point.  It’s academic right now, because an expression such as @1$ = .e won’t work.  The macro processor doesn’t expand @1$ to its string value and treat it as the left-hand side of an assignment.

As you surmised, .set or .= are used to set or change the value of an assembly-time variable—they are interchangeable.  These operators are very useful in defining stack frames, e.g.:

Code: Select all

;—————————————————————————————————————————————————————————
;
;LOCAL DEFINITIONS
;
.maxblk  =128                  ;max blocks per transaction +1
.s_cdb   =s_cdbg2              ;size of local CDB
.sfbase  .= 0                  ;base stack index
.sfidx   .= .sfbase            ;workspace index
;
;—————————> workspace stack frame start <—————————
;
.wsf     =.sfidx               ;start of workspace
;
.cdb     =.sfidx               ;local CDB
.sfidx   .= .sfidx+.s_cdb
.nblks   =.sfidx               ;block count
.sfidx   .= .sfidx+s_word
.lba     =.sfidx               ;LBA
.sfidx   .= .sfidx+s_lba
;
;—————————> workspace stack frame end <—————————
;
.s_wsf   =.sfidx-.sfbase       ;workspace size
.sfbase  .= .sfidx
;
;—————————> register stack frame start <—————————
;
.reg_dp  =.sfidx               ;DP
.sfidx   .= .sfidx+s_mpudpx
.reg_db  =.sfidx               ;DB
.sfidx   .= .sfidx+s_mpudbx
.reg_c   =.sfidx               ;.C
.sfidx   .= .sfidx+s_word
.reg_x   =.sfidx               ;.X
.sfidx   .= .sfidx+s_word
.reg_y   =.sfidx               ;.Y
.sfidx   .= .sfidx+s_word
.reg_sr  =.sfidx               ;SR
.sfidx   .= .sfidx+s_mpusrx
.reg_pc  =.sfidx               ;PC
.sfidx   .= .sfidx+s_mpupcx
	.if .def(_SCSI_)
.reg_pb  =.sfidx               ;PB
.sfidx   .= .sfidx+s_mpupbx
	.endif
;
;—————————> register stack frame end <—————————
;
.s_rsf   =.sfidx-.sfbase       ;register frame size
.sfbase  .= .sfidx
;
;—————————> parameter stack frame start <—————————
;
.idptr   =.sfidx               ;*SCSI_ID
.sfidx   .= .sfidx+s_dptr
.lbaptr  =.sfidx               ;*LBA
.sfidx   .= .sfidx+s_dptr
.nblkptr =.sfidx               ;*NBLK
.sfidx   .= .sfidx+s_dptr
.bufptr  =.sfidx               ;*BUF
.sfidx   .= .sfidx+s_dptr
;
;—————————> parameter stack frame end <—————————
;
.s_psf   =.sfidx-.sfbase       ;parameter frame size
;—————————————————————————————————————————————————————————
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Kowalski Simulator Updates

Post by BigDumbDinosaur »

Some assembler bugs over which I continue to trip—these are routinely encountered during 65C816 development:

  1. The .START pseudo-op complains if its argument is not a 16-bit value.  That prevents the use of .START in any source code that is to be assembled outside of bank $00.
     
  2. <abs>,Y addressing, when used in a program being assembled to other than bank $00, will error out and complain about 16-bit addressing.  Apparently, the assembler is tacking the bank onto the address, forming a 24-bit operand for an instruction that can only use absolute addressing.
     
  3. JMP (<abs>), JMP (<abs>,X) and JSR (<abs>,X) will all fail when used in a program being assembled to other than bank $00.  Apparently, the assembler is tacking the bank onto the address, forming a 24-bit operand for an instruction that can only use absolute indirect addressing.
     
  4. Search-and-replace persists in randomly crashing the editor.  It usually happens after a lot of changes have been made, suggesting there’s still an issue with the undo stack.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Kowalski Simulator Updates

Post by 8BIT »

HI BDD,

Thanks for the updated list of bugs. I've been really busy these past few months and have not had time for any hobbies. This list plus the BCD math errors are on my list of todo's.

thanks!
Daryl
Please visit my website -> https://sbc.rictor.org/
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Kowalski Simulator Updates

Post by BigDumbDinosaur »

8BIT wrote:
I've been really busy these past few months and have not had time for any hobbies.

Urk!  All work and no play, etc...  :D
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: Kowalski Simulator Updates

Post by Yuri »

Mean while I've been hard at work on the ported version! XD

(Also just got the parts in for my first SBC, so I've been sidetracked the last few days trying to debug the first version of that!)
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Kowalski Simulator Updates

Post by 8BIT »

I have finally finished up the latest round of bug fixes. These include:
- BCD 8-bit math errors - wrong values and wrong flags are working. I have not run an exhaustive test on the 16 bit code, but it does pass the test suite for fringe cases.
- <abs> addressing mode errors when above bank 0

Not fixed:
editor copy paste issues - this is more of a microsoft issue - I don't think my code can fix it.
.START directive not working above bank 0. - I had this fixed but that causes some strange issues with the simulator. Since the processor cannot start executing code above bank 0 without first switching to native mode, I'm not sure how effective .START will be with higher addresses. I have to research more. .START does not affect assembly, it only tells the simulator where to start executing from.

Latest files can be found here --> https://sbc.rictor.org/kowalski.html

thanks!
Daryl
Please visit my website -> https://sbc.rictor.org/
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: Kowalski Simulator Updates

Post by Yuri »

8BIT wrote:
I have finally finished up the latest round of bug fixes. These include:
- BCD 8-bit math errors - wrong values and wrong flags are working. I have not run an exhaustive test on the 16 bit code, but it does pass the test suite for fringe cases.
- <abs> addressing mode errors when above bank 0

Not fixed:
editor copy paste issues - this is more of a microsoft issue - I don't think my code can fix it.
.START directive not working above bank 0. - I had this fixed but that causes some strange issues with the simulator. Since the processor cannot start executing code above bank 0 without first switching to native mode, I'm not sure how effective .START will be with higher addresses. I have to research more. .START does not affect assembly, it only tells the simulator where to start executing from.

Latest files can be found here --> https://sbc.rictor.org/kowalski.html

thanks!
Daryl
I see some code was added to the IO window writing to an "output.txt" file. Not sure what it's for, seems like debugging code?


As for .START, I honestly feel it is some weird hack that shouldn't be there. The 6502 itself already defines a start vector in memory at FFFC/FFFD. Having the ability to override that in the UI for debugging is useful, but I don't think such a directive should even exist in the assembler.

(Same goes with all the IO window directives; really adds a bunch of cross cutting concerns that probably shouldn't be in the assembler to begin with.)

The way I'm handing that (currently) in the port is such:
If the UI's start address is invalid (i.e. UINT32_MAX), then use the start vector found at FFFC/FFFD. If the UI does have a valid address defined, use that.
User avatar
Yuri
Posts: 371
Joined: 28 Feb 2023
Location: Texas

Re: Kowalski Simulator Updates

Post by Yuri »

GitHub repo updated with latest changes.
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Kowalski Simulator Updates

Post by 8BIT »

Yep, output.txt generation was added to the output window for the BCD test cases. I forgot to remove it. It won't hurt anything for now as it gets reset on each invocation of the simulator. Thanks for catching my clumsiness!!

.START was included to allow for code to be compiled with data tables being placed before the code. .START would point the simulator to the desired start code. You do the same thing without it by adjusting the PC before running the sim. With the 65816, setting .START above bank 0 will start the code running, but the E bit is still set and many operands will be addressed in bank 0 vs the start bank. Clearing the E bit allows the code to run but I encountered some strange effects when invoking NMI and IRQ. Before I make the changes, I want to dig deeper and ensure I don't break other things too. The work around is to place some small startup code on bank 0 that gets the CPU into native mode and jumps to the desired START address above bank 0.

Thanks!
Daryl
Please visit my website -> https://sbc.rictor.org/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Kowalski Simulator Updates

Post by GARTHWILSON »

Daryl, the bottom of your page says, "Last updated on May 11, 2020."  Didn't you just update it again, with the newest simulator version?
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: Kowalski Simulator Updates

Post by 8BIT »

Yeah, The links to the files are up to date... I forget to update the footer. I'll fix that shortly.

thanks!
Please visit my website -> https://sbc.rictor.org/
Post Reply