My last major assembly-language project was on a PIC16 microcontroller which only has an 8-level return stack, and toward the end I was constantly overrunning it[...](The PIC16 is really mickey-mouse compared to the 6502, BTW.)

But seriously:Is the PIC16 also shoddier than the Intel 8080? We previously discussed its lack of useful indexed addressing modes other than moving the HL pointer around. Or the 8051? Are there criteria for what makes an architecture shoddy?

You know, you've suggested that the 8080/LR35902/Z80's poor complement of indexed addressing modes are some kind of fatal flaw a few times since that discussion; not to get into some kind of 8-bit instruction set holy war - I love the 6502 - but one could easily argue that the 6502's register paucity, or its huge number of obviously "missing" instructions (push and pull X or Y, for instance), or the aspects of its design that make it a poor target for C compilers are similarly debilitating. In practice, just as one learns to make effective use of the programming model of the 6502 (say, keeping a convention of storing temporaries on zero page, or using the 6502's powerful addressing modes to implement a more flexible software stack), so too does one learn to work with the Z80's strengths and limitations with things like structs-of-arrays rather than arrays-of-structs and page alignment. The comparison of the Z80 - a sophisticated-for-its-time general-purpose CPU that was selected over the 6502 for many computers and video game platforms throughout the 8-bit era - to a primitive microcontroller like the PIC16 (an 8-deep stack! my god! just look at this instruction set!), just because it can be a little clumsy with random access on structs or non-page aligned arrays, is practically offensive

At any rate, to answer your question so as to make my response a constructive contribution to the topic at hand rather than just a rant, there's of course no precise definition of what makes an architecture "Mickey Mouse" or not, but a couple of obvious things that make could make it feel less powerful or less ergonomic that come to mind are inconsistencies (different registers having different capabilities, for instance) or deficiencies that present roadblocks with no obvious workarounds (say, an incredibly shallow stack). In general, if across the range of problems you need to solve you need to spend a higher proportion of your time thinking about and writing code to work around the CPU instead of dealing with the problem at hand, you'll get the impression that a CPU is "Mickey Mouse".

Or, in even more general, a CPU is "Mickey Mouse" if it makes your life difficult

As someone who has an almost irrational fondness of the 8-bit PIC family, it's pretty terrible.

It's roughly comparable to the 8051, but with the big plus of both constant and very low interrupt latency compared to almost all other microcontrollers.

There are 5 major groups in the 8-bit PICs:

12-bit instruction word PICs, originating with the very first parts (PIC1640, PIC1650, &c). A few of the "PIC12xxx" parts now. Intended to control peripherals on a CP1600-based (yes, the one from the Intellivision) computer. One pointer access port, eight other hardware definition registers, and 23 more bytes of RAM for 32 total "first class" addresses. Everything else has to be addressed indirectly (pointer register) or via banking. Usually only two entries in the call stack. Maximum program size without bankswitching is 9 bits→512 instructions. Doesn't always support interrupts.

"older" 14-bit instruction word PICs. Usually "PIC16xxx" parts. Adds a real call stack (the 8-call deep that Garth was complaining about) as well as more bits for RAM (7 bits now, making 128 bytes). Its prettiest form is the PIC10F322, which is as much as you can fit without bankswitching. Maximum program size without bankswitching is 11 bits→2048 instructions.

"traditional" 16-bit instruction word PICs. PIC18xxx. Three pointer registers, 9 bits for specifying 512 bytes of "first class" RAM, of which half is used as a dedicated access to the bankswitching interface and half is dedicated for an "access" bank providing faster access to the I/O registers and some RAM. Added a set of "shadow registers" such that interrupts wouldn't require saving or restoring the main thread's state. Maximum program size is 23 bits→8M instructions.

These first three were designed to be source-level compatible; a PIC12F508 program could be reassembled for a PIC18F452 with very few (if any) changes.

"newer" 14-bit instruction word PICs. Usually "PIC16xxx" parts. Adds a second pointer register, to increase the ease of targeting C to it. Moves the original fixed registers around so it's no longer source-level compatible. Started growing all sorts of fun peripherals. Also acquired shadow registers.

"extended" 16-bit instruction word PICs. Supported alternate mode in all but the oldest PIC18xxx. Redefines the meaning of the 96 bytes of "access bank" to instead mean pointer-relative, i.e. for fast access of variables on a C stack.

But, remember, the original design, and what it excels at, is high speed first-class access to its own peripheral controls. C compatibility is an afterthought, and it shows. But a native asm interrupt handler that can reliably do something in a constant 5 instruction cycles from the original event? Sure. And almost all instructions take the same amount of time to execute, so constant-time code is much more tenable.

I love the 6502 - but one could easily argue that the 6502's register paucity, or its huge number of obviously "missing" instructions (push and pull X or Y, for instance), or the aspects of its design that make it a poor target for C compilers are similarly debilitating.

The CMOS 6502 (65c02) has been out for about 35 years and is still in production with no end in sight, unlike the NMOS which went out of production many years ago. The 65c02 does have push and pull X and Y (PHX, PLX, PHY, PLY), and quite a few others. The following is from my page on the differences between the NMOS and CMOS '02, at http://wilsonminesco.com/NMOS-CMOSdif/ :

STP DB SToP the processor until the next RST. ‾⌉ Power-supply current drops to nearly zero. | These two are | on WDC only.WAI CB WAIt. It's like STP, but any interrupt | will make it resume execution. Especially | useful for superfast interrupt response, | with zero latency. See interrupts primer. _⌋

Note: [1] Only the most-significant digit of the op code changes; so for example BBR'sop codes are 0F, 1F, 2F, 3F, 4F, 5F, 6F, and 7F, for BBR0 to BBR7. The bit number isspecified in the op code rather than the operand. These operate in ZP only. Rockwelladded these first, for their microcontrollers that had I/O in ZP. WDC added them inthe early 1990's. The Aug '92 data sheet shows the W65C02S available without them, andthe W65C02SB with them, but said eventually they would all have them, and be labeledW65C02S, without the B. By the July '96 data sheet, these instructions were standardin all of them.

CMOS 65c02 instructions' addressing modes that were not on the NMOS 6502:

In spite of my raking the PIC16 over the coals, I have become somewhat comfortable with it because of experience and the macros I have developed for it. One of the backwards-thinking things is the instructions saying for example "If such-and-such is true, then don't do the following." I have hidden that in the macros, like in the following routine which uses the macros but is also called by a macro so once it's in place, I don't have to keep seeing the ugly details. It's for displaying strings which could be in different pages of ROM:

Code:

; DISP_ROM_STRING below is for displaying strings from the program memory pages containing the strings. ; It is called in the DISP_ROM_STR macro. ; Displaying will start where cursor position variable CURSOR_POS says, which is zero-based, meaning 0 is top line, left end. ; MIN_CURSOR_POS is not used. ; CURSOR_POS will not get incremented here; but a CHR$(254) (þ) will do SET_LCD_ADR to the beginning of the 2nd line. ; Start with the low program-memory address byte of the string's 1st char, minus 1, in W. This will go into TEMP_1 and be the ; index to keep fetching the next byte of the string, incrementing TEMP_1 each time, until a 00 byte is read. ; Start with high byte of string addr in TEMP_4. ; Typical usage would be MOVLW HIGH str_adr, MOVWF TEMP_4, MOVLW LOW (str_addr - 1), CALL DISP_ROM_STRING. ; The entry W value for the first string in the page will be 0, even though that first char starts at addr xx01. ; You will often want to call CLR_LCD first. Note that CLR_LCD takes 5ms. The DISP_ROM_STR macro provides that option.

DISP_ROM_STRING: ; Uses TEMP_1, 2, 4, & LOOP_CNT_3. Start with ADL of desired string, minus 1, in W. MOVWF TEMP_1 ; The strings most often needed during signal generation should be in STR_TBL3, ; because shortness of program memory made me disable and enable interrupts in only MOVF CURSOR_POS, W ; one place, and I put the comparisons in reverse order because the STR_TBL1 section CALL SET_LCD_ADR ; has an additional (ADDLW H'FE') instruction. SET_LCD_ADR uses LCD_TEMP.

BEGIN ; Remember that writing to PCL makes PCLATH<4:0> get transferred to PCH. MOVF TEMP_4, W ; See which 256-byte page the desired string table is in. CASE CASE_OF_ HIGH STR_TBL3 ; In the case of it being in string table 3: COPY TEMP_4, TO, PCLATH ; We can't use the LOOK_UP macro here because of the MOVF / MOVLW difference. MOVF TEMP_1, W ; Get the index into the strings page back in W. CALL STR_TBL3 ; This is the PIC16 mickey-mouse lookup with RETLW's following the ADDWF PCL, F. CLRF PCLATH ; PCLATh must be cleared before the jump assembled by the END_OF. END_OF ; Now strings in STR_TBL3 will get interrupts enabled again sooner than others.

CASE_OF_ HIGH STR_TBL2 ; If we want the second string table, do this second part. COPY TEMP_4, TO, PCLATH ; We can't use the LOOK_UP macro here because of the MOVF / MOVLW difference. MOVF TEMP_1, W ; Get the index into the strings page back in W. CALL STR_TBL2 ; This is the PIC16 mickey-mouse lookup with RETLW's following the ADDWF PCL, F. CLRF PCLATH ; PCLATh must be cleared before the jump assembled by the END_OF. END_OF

; CASE_OF_ HIGH STR_TBL1 ; Here, by default, we need the first string table (hence the commenting-out). COPY TEMP_4, TO, PCLATH ; We can't use the LOOK_UP macro here because of the MOVF / MOVLW difference. MOVF TEMP_1, W ; Get the index into the strings page back in W. ADDLW H'FE' ; (This is because of the GOTO START at beginning of 256-byte page STR_TBL1 is in.) CALL STR_TBL1 ; This is the PIC16 mickey-mouse lookup with RETLW's following the ADDWF PCL, F. CLRF PCLATH ; PCLATh must be cleared before the jump assembled by the END_OF. ; END_OF_ END_CASE ANDLW H'FF' ; Unfortunately RETLW in STR_TBLs doesn't affect flags, and CLRF clears Z; hence this line. WHILE_NOT_ZERO ; If the byte fetched was non-0, we still have more of the string to display. SUBLW D'254' ; See if it's CHR$(254) which is to tell it to go to the next line. IF_EQ ; If it is, tell the LCD to go to addr $10, to skip CALL SET10 ; the rest of the top line. (It also can't increment across the boundary automatically.) ELSE_ ; Otherwise, SET_LCD_ADR uses LCD_TEMP. SUBLW D'254' ; (get our original number back which we had before the destructive compare-to-254 above) CALL WR_LCD_AUTO ; you can put it in the display without setting the address every time. Uses TEMP_2. END_IF INCF TEMP_1, F ; Get ready to check the next byte. REPEAT

I love the 6502 - but one could easily argue that the 6502's register paucity, or its huge number of obviously "missing" instructions (push and pull X or Y, for instance), or the aspects of its design that make it a poor target for C compilers are similarly debilitating.

The CMOS 6502 (65c02) has been out for about 35 years and is still in production with no end in sight, unlike the NMOS which went out of production many years ago. The 65c02 does have push and pull X and Y (PHX, PLX, PHY, PLY), and quite a few others.

Sure, but this is an NESdev site, the NES has an NMOS 6502 derivative without those instructions, and tepples (who broached the question) has done tons of NES/NMOS 6502 development. The point wasn't to disparage the 65(c)02 in particular, simply to point out that most microcomputer CPUs of the mid 70s have quirks and frustrating limitations that need to be worked around - including CPUs that tepples presumably wouldn't describe as "Mickey Mouse".

Out of curiosity, had you ever done any work for the Mitsumi 740 microcontrollers?

Should that say "Mitsubishi"? I know there was a Mitsubishi microcontroller (µC) with a 65c02 at its heart, but Howard Speegle, an old but still very active and productive man who owns Diva Automation, was using them for some products he was selling, but Mits started demanding larger and larger minimum orders until it got so he could no longer continue. Four years ago, he sent me an email, part of which is quoted below. He gave me permission to use his material on forums where it would help promote the 6502.

The 6502 architecture remains nearly ideal in my book. It is so sweet and regular that it is hard to screw up without great effort. I once wrote a debug/monitor for the 6502 while waiting for my car to be serviced, assembled it in my head, drove back to the office, typed the machine code into an EPROM programmer, drove to my customer and plugged the EPROM into his system. Unsurprisingly, it worked. I could not do that with any other architecture I have ever seen. I'm not bragging, I am simply describing the end result of an excellent design, that could support such a process.

Now, after 54 years in the business, I still love the 6502, but have abandoned it for new designs simply because the only manufacturer [talking about Mits?] of this beautiful design finally succeeded in driving me away, after 20 years of fighting them to be able to purchase small quantities.

I designed my first multi-axis motion controller in 1985, using five 6502s. Each axis had a dedicated processor and the fifth one was for communications and program sequencing.

The second generation design followed very quickly. It was obvious that a single 6502 could service four axes of digital servo control without breaking a sweat and could also handle the system-level chores while leaving around 30% of capacity as performance margin.

Very shortly afterward, I discovered that Mitsubishi was producing a microcontroller with a lovely set of on-board peripherals integrated extremely well with a 6502 core. I don't know who was responsible for this superb integration, but it was beautifully melded with the 6502 architecture and retained the same direct and regular concepts of the 6502. It was not only a pleasure to use, but it was implemented in CMOS and was offered in a version that could be clocked at 10 MHz.

I was ecstatic until I learned that Mitsubishi hated small accounts even more so than Intel did. Every step of the way from my first order in 1986 until my last in about 2004, I had to force them to sell to me. They did not wan to sell me the chips, nor the assembler nor any support elements and certainly never provided any design support of any sort. When Mitsubishi merged their microcontroller products under the name Renasas, they never informed me. All I knew was that I was no longer able to buy the parts I needed to fulfill orders from my customers.

Eventually, I learned about Renasas and continued with them because to me, this was the most ideal circuit available on the market.

There finally came a time when I gave up. It was becoming almost impossible to be allowed to buy parts from Renasas and then only by ordering 2000-piece minimums and waiting months for delivery. The last straw was when all the competition added on-board flash and oscillators and Renasas only offered such things on the M16, which was not 6502-based.

Why should I continue fighting with a company like this when they would not support my beloved 6502? So I began to evaluate the competition. I won't go into the details of my selection, but I can say that if I had known that the highly trumpeted support for the Atmel AVR family did not truly exist, I might have chosen a different vehicle.

As it is, I am stuck, for the moment, with a silly mnemonic structure in the assembly language that leaves me longing for the regularity of the 6502, and am no fan of the Harvard architecture that separates program, memory and I/O buses and certainly not of the lingering smell of the Intel 8051, but at least this design was performed by a group that had at least seen a real computer, as opposed to the 80xxx crap.

The first dot matrix printer my family had used one of the 740 family microcontrollers, and for whatever reason we've kept it even as we threw away newer hardware. When I finally did the sleuthing to figure out what it was, I was kinda awed by having a slightly-weirdly-shaped 65C02 inside (since opcode locations differed).

Who is online

Users browsing this forum: No registered users and 4 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum