Page 29 of 32

Re: Kowalski Simulator Updates

Posted: Sat Dec 28, 2024 1:05 am
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:

Re: Kowalski Simulator Updates

Posted: Sat Dec 28, 2024 4:31 am
by GARTHWILSON
That is a neat idea though!

Re: Kowalski Simulator Updates

Posted: Sat Dec 28, 2024 6:01 am
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.

Re: Kowalski Simulator Updates

Posted: Sat Dec 28, 2024 5:01 pm
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...

Re: Kowalski Simulator Updates

Posted: Sun Dec 29, 2024 7:24 am
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
;—————————————————————————————————————————————————————————

Re: Kowalski Simulator Updates

Posted: Sun Jan 26, 2025 5:57 am
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.

Re: Kowalski Simulator Updates

Posted: Sun Jan 26, 2025 6:30 am
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

Re: Kowalski Simulator Updates

Posted: Sun Jan 26, 2025 3:26 pm
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

Re: Kowalski Simulator Updates

Posted: Mon Jan 27, 2025 6:54 am
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!)

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 6:10 pm
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

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 7:29 pm
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.

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 7:54 pm
by Yuri
GitHub repo updated with latest changes.

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 8:01 pm
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

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 10:36 pm
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?

Re: Kowalski Simulator Updates

Posted: Fri Feb 07, 2025 11:19 pm
by 8BIT
Yeah, The links to the files are up to date... I forget to update the footer. I'll fix that shortly.

thanks!