• [OT] SPARC (was Re: The integral type 'byte')

    From Janis Papanagnou@21:1/5 to Chris M. Thomasson on Fri Mar 28 03:26:26 2025
    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like the
    frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that branch
    delay slot? Ever use it with a MEMBAR instruction? Shit would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC on
    assembler level, just studied some documents. I'm not even sure the
    term "frame shift on the stack" that I used is accurate or correct;
    it's just an informal description of a technical detail that I had
    considered to be interesting. (Instead of copying parameters/results
    with function calls between callers and callee you could just shift
    a "stack window" by adjusting a register (or so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Fri Mar 28 13:26:23 2025
    On Fri, 28 Mar 2025 03:26:26 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like the
    frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that
    branch delay slot? Ever use it with a MEMBAR instruction? Shit
    would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC on assembler level, just studied some documents. I'm not even sure the
    term "frame shift on the stack" that I used is accurate or correct;
    it's just an informal description of a technical detail that I had
    considered to be interesting. (Instead of copying parameters/results
    with function calls between callers and callee you could just shift
    a "stack window" by adjusting a register (or so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis


    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.
    Could I guess that you didn't ever programmed in 68K asm, x86 asm,
    NS32k asm, MIPS asm etc... ? Could I guess that your reading of
    respective ISA docs was also similarly shallow? Could I guess that the
    only non-8-bitters that you ever programmed in asm were one or couple
    of TMS3202x DSPs?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Fri Mar 28 13:08:14 2025
    On 28/03/2025 11:26, Michael S wrote:
    On Fri, 28 Mar 2025 03:26:26 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like the
    frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that
    branch delay slot? Ever use it with a MEMBAR instruction? Shit
    would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC on
    assembler level, just studied some documents. I'm not even sure the
    term "frame shift on the stack" that I used is accurate or correct;
    it's just an informal description of a technical detail that I had
    considered to be interesting. (Instead of copying parameters/results
    with function calls between callers and callee you could just shift
    a "stack window" by adjusting a register (or so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis


    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    I have not programmed SPARC either, but I would not consider branch
    delay slots to be a distinguishing feature - delay slots were a common
    feature in many (but not all) RISC architectures - most notably, IMHO, MIPS.

    The register window concept, however, was a lot less common (though not
    unique to the SPARC), and much more relevant to the way you work with
    the processor.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Fri Mar 28 13:20:35 2025
    On 28.03.2025 11:26, Michael S wrote:

    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    Yes. I clearly said that; I spoke about a technical detail that
    I found interesting, no more, no less.

    Could I guess that you didn't ever programmed in 68K asm, x86 asm,
    NS32k asm, MIPS asm etc... ? Could I guess that your reading of
    respective ISA docs was also similarly shallow? Could I guess that the
    only non-8-bitters that you ever programmed in asm were one or couple
    of TMS3202x DSPs?

    Just to understand; do you consider the 68k to be an "8-bitter"?
    (Are you taking the address bus, the data bus, or the addressable
    memory unit as the interesting "N-bitter" number?)

    My engagement with each CPU I clearly mentioned in my posts.
    For your convenience I can summarize;

    6502 - programmed with it (at an office equipment shop)
    SC 61860 - programmed with it (at home)
    some Intel (I forgot the number) - in a University course
    8080 - at the University
    M1/M2/M3 [Seegmüller] - programmed with it (University)
    68000 - programmed with it (on an Atari I owed)
    TMS 320 C25 - programmed with it (at the DLR)
    SPARC - read briefly about it
    NS 32016/32 - read about it

    I never spoke about MIPS here, nor about other CPUs of systems
    that I worked with (e.g. Power PC). I also never programmed the
    CPU of my current computers at home on assembler level; I don't
    even recall what CPUs they have. - Since the late 1989 I didn't
    care any more about CPUs, let alone about their programming; I
    was solely using high-level languages.

    HTH.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to David Brown on Fri Mar 28 15:20:36 2025
    On Fri, 28 Mar 2025 13:08:14 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 28/03/2025 11:26, Michael S wrote:
    On Fri, 28 Mar 2025 03:26:26 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like
    the frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that
    branch delay slot? Ever use it with a MEMBAR instruction? Shit
    would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC
    on assembler level, just studied some documents. I'm not even sure
    the term "frame shift on the stack" that I used is accurate or
    correct; it's just an informal description of a technical detail
    that I had considered to be interesting. (Instead of copying
    parameters/results with function calls between callers and callee
    you could just shift a "stack window" by adjusting a register (or
    so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis


    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    I have not programmed SPARC either, but I would not consider branch
    delay slots to be a distinguishing feature - delay slots were a
    common feature in many (but not all) RISC architectures - most
    notably, IMHO, MIPS.

    The register window concept, however, was a lot less common (though
    not unique to the SPARC), and much more relevant to the way you work
    with the processor.


    Register Window is a major part of Berkeley tradition. The processor
    with Register Window that was sold and highest quantities is probably
    not SPARC, but Intel i960. Another examples are AMD 29K and Intel
    Itanium.

    As to importance for asm coder, branch delay slot is more important
    (i.e. more annoying) than register window, simply because in typical
    program one has more branches than function calls.
    At system programming level register window can be more important, in a
    bad way.
    At the level of programming in C, esp. for application programs, both
    register windows and branch delay slots are transparent.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Janis Papanagnou on Fri Mar 28 15:56:10 2025
    On Fri, 28 Mar 2025 13:20:35 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 11:26, Michael S wrote:

    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    Yes. I clearly said that; I spoke about a technical detail that
    I found interesting, no more, no less.

    Could I guess that you didn't ever programmed in 68K asm, x86 asm,
    NS32k asm, MIPS asm etc... ? Could I guess that your reading of
    respective ISA docs was also similarly shallow? Could I guess that
    the only non-8-bitters that you ever programmed in asm were one or
    couple of TMS3202x DSPs?

    Just to understand; do you consider the 68k to be an "8-bitter"?

    No, 68K was sold as "16-bit", but by modern use of the terms it is
    32-bit CPU.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Michael S on Fri Mar 28 14:20:56 2025
    On 28.03.2025 13:56, Michael S wrote:
    On Fri, 28 Mar 2025 13:20:35 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    Just to understand; do you consider the 68k to be an "8-bitter"?

    No, 68K was sold as "16-bit", but by modern use of the terms it is
    32-bit CPU.

    Thanks for clarifying.

    IIRC, I was certainly addressing and manipulating 8, 16, and 32 bit
    entities with it. But it annoyed me to have a restriction that some
    data manipulations required a 2-byte (or 4-byte?) alignment of data
    (as far as memory serves). - Probably justifiable with it being a
    "16-bitter". - Ah, well, anyway, never mind.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Janis Papanagnou on Fri Mar 28 15:43:09 2025
    On 28/03/2025 14:20, Janis Papanagnou wrote:
    On 28.03.2025 13:56, Michael S wrote:
    On Fri, 28 Mar 2025 13:20:35 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    Just to understand; do you consider the 68k to be an "8-bitter"?

    No, 68K was sold as "16-bit", but by modern use of the terms it is
    32-bit CPU.


    I have no idea how it was marketed, but I have always considered the 68k
    as a 32-bit architecture. The 68000 had a 16-bit ALU and 16-bit
    databus, but its GPR's and address registers were 32-bit, and most
    instructions handled up to 32-bit data. The 68020 had a 32-bit ALU and
    32-bit buses, and was 32-bit by most measurements (there being no
    standard as to what "N-bit cpu" actually means). To my mind, since the
    68000 and 68020 had the same ISA, it makes no sense to say that one of
    these was 16-bit and the other 32-bit.

    Marketing folks, of course, have other ideas!

    (The 68k device I used most was the 68332 microcontroller, whose cpu
    core was a modified 68020 core. I also used a few Coldfires later on.)

    Thanks for clarifying.

    IIRC, I was certainly addressing and manipulating 8, 16, and 32 bit
    entities with it. But it annoyed me to have a restriction that some
    data manipulations required a 2-byte (or 4-byte?) alignment of data
    (as far as memory serves). - Probably justifiable with it being a "16-bitter". - Ah, well, anyway, never mind.


    Natural alignment of data, up to the size of the normal accesses for the
    chip, has always seemed entirely natural to me. I can't tell you if the
    68k device I used - the 68332 - could or could not handle misaligned
    accesses, because it's not something I would normally do.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Michael S on Fri Mar 28 15:33:59 2025
    On 28/03/2025 13:20, Michael S wrote:
    On Fri, 28 Mar 2025 13:08:14 +0100
    David Brown <david.brown@hesbynett.no> wrote:

    On 28/03/2025 11:26, Michael S wrote:
    On Fri, 28 Mar 2025 03:26:26 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like
    the frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that
    branch delay slot? Ever use it with a MEMBAR instruction? Shit
    would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC
    on assembler level, just studied some documents. I'm not even sure
    the term "frame shift on the stack" that I used is accurate or
    correct; it's just an informal description of a technical detail
    that I had considered to be interesting. (Instead of copying
    parameters/results with function calls between callers and callee
    you could just shift a "stack window" by adjusting a register (or
    so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis


    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    I have not programmed SPARC either, but I would not consider branch
    delay slots to be a distinguishing feature - delay slots were a
    common feature in many (but not all) RISC architectures - most
    notably, IMHO, MIPS.

    The register window concept, however, was a lot less common (though
    not unique to the SPARC), and much more relevant to the way you work
    with the processor.


    Register Window is a major part of Berkeley tradition. The processor
    with Register Window that was sold and highest quantities is probably
    not SPARC, but Intel i960. Another examples are AMD 29K and Intel
    Itanium.

    I did not know that the Itanium had a register window - I did know about
    the AMD 29K. It surprises me to hear that the i960 was sold in higher quantities than the SPARC, but since I have no real idea of the sales
    figures of either, I will take your word for it.


    As to importance for asm coder, branch delay slot is more important
    (i.e. more annoying) than register window, simply because in typical
    program one has more branches than function calls.

    I would disagree. Neither feature is particularly relevant if you are
    doing user-level programming in a high-level language. In assembly, you
    have no choice but to understand and use the register window feature -
    it's a major part of coding. The branch delay slot, on the other hand,
    can be ignored by simply using a NOP, for a slight efficiency cost. I
    vaguely recall the MIPS assembler handling delay slots somewhat
    automatically, but my experience using that was /very/ brief. Make the
    most of the delay slot for optimal efficiency would, I expect, be
    annoying - but so is a lot of assembly coding for RISC devices!


    At system programming level register window can be more important, in a
    bad way.
    At the level of programming in C, esp. for application programs, both register windows and branch delay slots are transparent.


    Yes.

    Any classification of "distinguishing features" or "important features"
    is going to be quite subjective - it depends which other cpus you are
    comparing to.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to David Brown on Fri Mar 28 17:45:25 2025
    On 2025-03-28, David Brown <david.brown@hesbynett.no> wrote:
    On 28/03/2025 11:26, Michael S wrote:
    On Fri, 28 Mar 2025 03:26:26 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 03:03, Chris M. Thomasson wrote:
    On 3/27/2025 6:59 PM, Janis Papanagnou wrote:

    But there were ideas! But not only the interesting ideas (like the
    frame shift on the stack [SPARC]; one detail I memorized)

    It's been a while since I coded up raw SPARC ASM. Remember that
    branch delay slot? Ever use it with a MEMBAR instruction? Shit
    would hit the fan.

    As mentioned somewhere upthread I haven't ever programmed a SPARC on
    assembler level, just studied some documents. I'm not even sure the
    term "frame shift on the stack" that I used is accurate or correct;
    it's just an informal description of a technical detail that I had
    considered to be interesting. (Instead of copying parameters/results
    with function calls between callers and callee you could just shift
    a "stack window" by adjusting a register (or so).

    So, no, I cannot remember a "branch delay slot". - Sorry. - Want to
    elaborate on the story?

    Janis


    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    I have not programmed SPARC either, but I would not consider branch
    delay slots to be a distinguishing feature - delay slots were a common feature in many (but not all) RISC architectures - most notably, IMHO, MIPS.

    I believe it was common for assemblers to hide branch delay slots from
    the programmer by inserting the no-op instructions into them
    automatically, so you wouldn't have to think about them, unless you
    wanted to take advantage of them.

    I don't remember the details. I seem to recall that one way of doing it
    is to have a different mnemonic for a branch pseudo-instruction which
    inserts the no-op into the following delay slot, versus a mnemonic
    that gives you the raw instruction, following which you have to put
    something into the delay slot yourself.

    I also seem to recall that at least one of the mainstrema RISC families
    made the mistake of varying the number of branch delay slots across
    family members (as the pipelines got deeper), so that code for an older
    chip wouldn't run due to not having enough instructions in the delay
    slot.

    Janis could have easily worked in assembly on a processor without
    being aware of branch delay slots.


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to David Brown on Fri Mar 28 17:46:49 2025
    On 2025-03-28, David Brown <david.brown@hesbynett.no> wrote:
    I did not know that the Itanium had a register window - I did know about

    We can also remark that the Itanium had a cultural registration window
    for becoming popular, and missed it.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Michael S on Fri Mar 28 17:54:13 2025
    On 2025-03-28, Michael S <already5chosen@yahoo.com> wrote:
    On Fri, 28 Mar 2025 13:20:35 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 28.03.2025 11:26, Michael S wrote:

    You didn't ever programmed in SPARC asm. Your reading of SPARC
    documents was so shallow that you didn't pay attention to highly
    visible distinguishing feature as branch delay slot.

    Yes. I clearly said that; I spoke about a technical detail that
    I found interesting, no more, no less.

    Could I guess that you didn't ever programmed in 68K asm, x86 asm,
    NS32k asm, MIPS asm etc... ? Could I guess that your reading of
    respective ISA docs was also similarly shallow? Could I guess that
    the only non-8-bitters that you ever programmed in asm were one or
    couple of TMS3202x DSPs?

    Just to understand; do you consider the 68k to be an "8-bitter"?

    No, 68K was sold as "16-bit", but by modern use of the terms it is
    32-bit CPU.

    It was probably a mistake to sell it that way.

    While 16 bit would have assured systems designers that the processor
    could work with existing hardware design based around a 16 bit
    data buses, it kind of undersold the processor.

    Can you imagine; you design a processor with a decent number of 32 bit
    address and data registers, and internal data paths. And then your
    sales people go around with 16 bit narratives.

    I wonder whether, had the MC86K featured a 32x32->64 multiplication
    instruction (later featured in the MC68020), would it still have
    been sold as 16 bit?


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Chris M. Thomasson on Fri Mar 28 18:44:33 2025
    On 2025-03-28, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
    I also remember reading in some SPARC manual about using NOP's in branch delay slots. Programming the SPARC was really "fun" when it was in RMO mode... :^)

    I fixed a bug in GCC almost 20 years ago. It was incorrectly filling
    a branch delay slot on MIPS, due to a mistake in the callee-saved
    register determination:

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34456

    What ended up happening was that we had shared library functions being
    called using the wrong global-offset-table pointer (that of the
    caller rather than their correct one) resulting in a function call
    going into an entirely wrong function due to register $28 (GOT)
    being wrongly set.

    When you put an instruction in the branch delay slot of a conditional
    branch, you have to be sure that it's okay to execute that instruction
    in both the taken and not-taken path.

    If the instruction is taken from the earlier stream, this is
    always OK. I.e. if we change this:

    insn0
    bz elsewhere
    nop
    insn1

    to this:

    bz elsewhere
    insn0
    insn1

    where we of course have ot be sure that we can reorder insn0 past the
    bz instruction.

    Usually the branch delayed slot is filled from the target of the branch:

    insn0
    bz elsewhere
    insnX ;; first instruction of elsewhere block moved here
    insn1

    If this is a regular branch delay slot, insnX will be executed in
    the not-taken path.

    We need careful analysis to determine that executing the instruction is
    okay in the not-taken path, even though it borrowed from a completely
    unrelated elsewhere block.

    It is okay, for instance, if it clobbers a register that is dead
    in the not-taken path.

    insn0
    bz elsewhere
    move R3, R5 ; OK to move this here: R3 dead
    move R9, (R13 + 8) ; R3 dead here
    move R3, R7 ; R3 dead because of this.

    The move R3, R5 instruction doesn't matter because R3 is dead in the
    not-taken path. It is dead because the next time it is referenced, it is
    the target of a store; its value is never used.

    What was happening here is that an instruction to set up the global
    offset pointer, register R28 (or $28) was being moved into the
    branch delay slot.

    bz elsewhere ;; elsewhere makes a call to a shared library
    move R28, whaetver ;; wrongly moved: set up GP for that library
    call something ;; R28 wrongly believed dead

    GCC though it was okay to put the R28 instruction into the delay
    slot because R28 is a register that is clobbered by the function
    call in the not-taken path.

    Registers that are not callee-saved are considered dead before
    a function call; it is assumed the callee clobbers them and so
    their current values are not required.

    GCC mistakenly considered register $28, the global pointer,
    to be callee-clobbered. But in fact it is not, and the
    function invoked relied on it having the prior value.

    (There is a feature called annulled delay slots. That's why the bug
    report refers to non-annulled. An annulled delay slot would not have
    this problem. An anulled delay slot is flagged such that the
    branch-not-taken straight path will skip the instruction.
    You can blindly move an instruction from the branch target into an
    annulled delay slot, without worrying whether it clobbers a live
    register.)

    It was a tough debug. Analyzing the crash and determining it was from a
    bad $28 pointer, noticing that it's set in a branch delay slot
    as the easy part. After that, I had to ramp up on the
    spaghetti-like, labyrinthine gcc internals (full of ugly macros not
    resolvable in gdb) far enough that I was able to actually single step
    through a basic block optimization in GDB, somehow printing out the
    INSNS as they are being visited, and thereby I saw where it was
    getting to the branch at the end of the basic block and incorrectly
    handling the branch delay slot.

    I'm not sure I'd have the energy to dive into someone's open source
    ball of mud that deeply today, just for the sake of a "drive by"
    bugfix.

    I was driven because I was in a startup surrounded by people who
    believed I could do anything, and I probably subconsciously wanted to
    live up that.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)