2020-12-16 11:41:37 +00:00
<!DOCTYPE html>
< html lang = "en" >
2012-03-23 20:30:31 +00:00
< head >
2020-12-16 11:41:37 +00:00
< meta charset = "utf-8" / >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" / >
2021-06-25 01:27:09 +00:00
< meta name = "generator" content = "HelpNDoc Personal Edition 7.3.0.348" >
2020-12-16 11:41:37 +00:00
< meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< link rel = "icon" href = "favicon.ico" / >
< title > CPU - 6502< / title >
< meta name = "description" content = "" / >
< meta name = "keywords" content = "" >
<!-- Twitter Card data -->
< meta name = "twitter:card" content = "summary" >
< meta name = "twitter:title" content = "CPU - 6502" >
< meta name = "twitter:description" content = "" >
<!-- Open Graph data -->
< meta property = "og:title" content = "CPU - 6502" / >
< meta property = "og:type" content = "article" / >
< meta property = "og:description" content = "" / >
< meta property = "og:site_name" content = "FCEUX Help" / >
<!-- Bootstrap core CSS -->
< link href = "vendors/bootstrap-3.4.1/css/bootstrap.min.css" rel = "stylesheet" / >
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
< link href = "vendors/bootstrap-3.4.1/css/ie10-viewport-bug-workaround.css" rel = "stylesheet" / >
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- [if lt IE 9]>
< script src = "vendors/html5shiv-3.7.3/html5shiv.min.js" > < / script >
< script src = "vendors/respond-1.4.2/respond.min.js" > < / script >
<![endif]-->
<!-- JsTree styles -->
< link href = "vendors/jstree-3.3.10/themes/default/style.min.css" rel = "stylesheet" / >
<!-- Hnd styles -->
< link href = "css/layout.min.css" rel = "stylesheet" / >
< link href = "css/effects.min.css" rel = "stylesheet" / >
< link href = "css/theme-light-blue.min.css" rel = "stylesheet" / >
< link href = "css/print.min.css" rel = "stylesheet" media = "print" / >
< style type = "text/css" > nav { width : 250 px } @ media screen and ( min-width : 769px ) { body . md-nav-expanded div # main { margin-left : 250 px } body . md-nav-expanded header { padding-left : 264 px } } < / style >
<!-- Content style -->
< link href = "css/hnd.content.css" rel = "stylesheet" / >
2012-03-23 20:30:31 +00:00
< / head >
2020-12-16 11:41:37 +00:00
< body class = "md-nav-expanded" >
2012-03-23 20:30:31 +00:00
2020-12-16 11:41:37 +00:00
< div id = "skip-link" >
< a href = "#main-content" class = "element-invisible" > Skip to main content< / a >
< / div >
< header class = "headroom" >
< button class = "hnd-toggle btn btn-default" >
< span class = "sr-only" > Toggle navigation< / span >
< span class = "icon-bar" > < / span > < span class = "icon-bar" > < / span > < span class = "icon-bar" > < / span >
< / button >
< h1 > FCEUX Help< / h1 >
< / header >
< nav id = "panel-left" class = "md-nav-expanded" >
<!-- Nav tabs -->
< ul class = "tab-tabs nav nav-tabs" role = "tablist" >
< li id = "nav-close" >
< button class = "hnd-toggle btn btn-default" >
< span class = "glyphicon glyphicon-remove" aria-hidden = "true" > < / span >
< / button >
< / li >
< li role = "presentation" class = "tab active" >
< a href = "#contents" id = "tab-contents" aria-controls = "contents" role = "tab" data-toggle = "tab" >
< i class = "glyphicon glyphicon-list" > < / i >
Contents
< / a >
< / li >
< li role = "presentation" class = "tab" >
< a href = "#index" id = "tab-index" aria-controls = "index" role = "tab" data-toggle = "tab" >
< i class = "glyphicon glyphicon-asterisk" > < / i >
Index
< / a >
< / li >
< li role = "presentation" class = "tab" >
< a href = "#search" id = "tab-search" aria-controls = "search" role = "tab" data-toggle = "tab" >
< i class = "glyphicon glyphicon-search" > < / i >
Search
< / a >
< / li >
< / ul > <!-- /Nav tabs -->
<!-- Tab panes -->
< div class = "tab-content" >
< div role = "tabpanel" class = "tab-pane active" id = "contents" >
< div id = "toc" class = "tree-container unselectable"
data-url="_toc.json"
data-openlvl="1"
>
< / div >
< / div > <!-- /contents -->
< div role = "tabpanel" class = "tab-pane" id = "index" >
< div id = "keywords" class = "tree-container unselectable"
data-url="_keywords.json"
data-openlvl="1"
>
< / div >
< / div > <!-- /index -->
< div role = "tabpanel" class = "tab-pane" id = "search" >
< div class = "search-content" >
< div class = "search-input" >
< form id = "search-form" >
< div class = "form-group" >
< div class = "input-group" >
< input type = "text" class = "form-control" id = "input-search" name = "input-search" placeholder = "Search..." / >
< span class = "input-group-btn" >
< button class = "btn btn-default" type = "submit" >
< span class = "glyphicon glyphicon-search" aria-hidden = "true" > < / span >
< / button >
< / span >
< / div >
< / div >
< / form >
< / div > <!-- /search - input -->
< div class = "search-result" >
< div id = "search-info" > < / div >
< div class = "tree-container unselectable" id = "search-tree" > < / div >
< / div > <!-- /search - result -->
< / div > <!-- /search - content -->
< / div > <!-- /search -->
< / div > <!-- /Tab panes -->
< / nav >
< div id = "main" >
< article >
< div id = "topic-content" class = "container-fluid"
data-hnd-id="6502CPU"
data-hnd-context="32"
data-hnd-title="CPU - 6502"
>
< div class = "navigation" >
< ol class = "breadcrumb" >
< li > < a href = "Technicalinformation.html" > Technical Information< / a > < / li > < li > < a href = "NESProcessor.html" > NES Processing< / a > < / li >
< / ol >
< div class = "nav-arrows" >
2021-06-25 01:27:09 +00:00
< div class = "btn-group btn-group" role = "group" > < a class = "btn btn-default" href = "NESProcessor.html" title = "NES Processing" role = "button" > < span class = "glyphicon glyphicon-menu-up" aria-hidden = "true" > < / span > < / a > < a class = "btn btn-default" href = "NESProcessor.html" title = "NES Processing" role = "button" > < span class = "glyphicon glyphicon-menu-left" aria-hidden = "true" > < / span > < / a > < a class = "btn btn-default" href = "PPU.html" title = "PPU - 2C02" role = "button" > < span class = "glyphicon glyphicon-menu-right" aria-hidden = "true" > < / span > < / a > < / div >
2020-12-16 11:41:37 +00:00
< / div >
< / div >
< a id = "main-content" > < / a >
< h2 > CPU - 6502< / h2 >
< div class = "main-content" >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # $Id: 6502_cpu.txt,v 1.1.1.1 2004/08/29 01:29:35 bryan Exp $< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # This file is part of Commodore 64 emulator< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # and Program Development System.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # See README for copyright notice< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # This file contains documentation for 6502/6510/8500/8502 instruction set.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Written by< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # John West (john@ucc.gu.uwa.edu.au)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Marko MЉkelЉ (msmakela@kruuna.helsinki.fi)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # $Log: 6502_cpu.txt,v $< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.1.1.1 2004/08/29 01:29:35 bryan< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # no message< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.1 2002/05/21 00:42:27 xodnizel< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # updates< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.8 1994/06/03 19:50:04 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Patchlevel 2< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.7 1994/04/15 13:07:04 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # 65xx Register descriptions added< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.6 1994/02/18 16:09:36 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.5 1994/01/26 16:08:37 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # X64 version 0.2 PL 1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.4 1993/11/10 01:55:34 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.3 93/06/21 13:37:18 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # X64 version 0.2 PL 0< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # Revision 1.2 93/06/21 13:07:15 jopi< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # *** empty log message ***< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > #< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > Note: To extract the uuencoded ML programs in this article most< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > easily you may use e.g. "uud" by Edwin Kremer ,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > which extracts them all at once.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Documentation for the NMOS 65xx/85xx Instruction Set< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 Instructions by Addressing Modes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6502 Registers< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510/8502 Undocumented Commands< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Register selection for load and store< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Decimal mode in NMOS 6500 series< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 features< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Different CPU types< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 Instruction Timing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > How Real Programmers Acknowledge Interrupts< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Memory Management< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Autostart Code< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Notes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > References< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 Instructions by Addressing Modes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > off- ++++++++++ Positive ++++++++++ ---------- Negative ----------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > set 00 20 40 60 80 a0 c0 e0 mode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +00 BRK JSR RTI RTS NOP* LDY CPY CPX Impl/immed< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +01 ORA AND EOR ADC STA LDA CMP SBC (indir,x)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +02 t t t t NOP*t LDX NOP*t NOP*t ? /immed< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +03 SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* (indir,x)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +04 NOP* BIT NOP* NOP* STY LDY CPY CPX Zeropage< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +05 ORA AND EOR ADC STA LDA CMP SBC Zeropage< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +06 ASL ROL LSR ROR STX LDX DEC INC Zeropage< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +07 SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Zeropage< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +08 PHP PLP PHA PLA DEY TAY INY INX Implied< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +09 ORA AND EOR ADC NOP* LDA CMP SBC Immediate< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0a ASL ROL LSR ROR TXA TAX DEX NOP Accu/impl< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0b ANC** ANC** ASR** ARR** ANE** LXA** SBX** SBC* Immediate< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0c NOP* BIT JMP JMP () STY LDY CPY CPX Absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0d ORA AND EOR ADC STA LDA CMP SBC Absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0e ASL ROL LSR ROR STX LDX DEC INC Absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +0f SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +10 BPL BMI BVC BVS BCC BCS BNE BEQ Relative< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +11 ORA AND EOR ADC STA LDA CMP SBC (indir),y< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +12 t t t t t t t t ?< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +13 SLO* RLA* SRE* RRA* SHA** LAX* DCP* ISB* (indir),y< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +14 NOP* NOP* NOP* NOP* STY LDY NOP* NOP* Zeropage,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +15 ORA AND EOR ADC STA LDA CMP SBC Zeropage,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +16 ASL ROL LSR ROR STX y) LDX y) DEC INC Zeropage,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +17 SLO* RLA* SRE* RRA* SAX* y) LAX* y) DCP* ISB* Zeropage,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +18 CLC SEC CLI SEI TYA CLV CLD SED Implied< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +19 ORA AND EOR ADC STA LDA CMP SBC Absolute,y< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1a NOP* NOP* NOP* NOP* TXS TSX NOP* NOP* Implied< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1b SLO* RLA* SRE* RRA* SHS** LAS** DCP* ISB* Absolute,y< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1c NOP* NOP* NOP* NOP* SHY** LDY NOP* NOP* Absolute,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1d ORA AND EOR ADC STA LDA CMP SBC Absolute,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1e ASL ROL LSR ROR SHX**y) LDX y) DEC INC Absolute,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > +1f SLO* RLA* SRE* RRA* SHA**y) LAX* y) DCP* ISB* Absolute,x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > ROR intruction is available on MC650x microprocessors after< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > June, 1976.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Legend:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > t Jams the machine< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > *t Jams very rarely< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > * Undocumented command< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ** Unusual operation< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > y) indexed using Y instead of X< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > () indirect instead of absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Note that the NOP instructions do have other addressing modes than the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > implied addressing. The NOP instruction is just like any other load< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instruction, except it does not store the result anywhere nor affects the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > flags.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6502 Registers< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The NMOS 65xx processors are not ruined with too many registers. In addition< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to that, the registers are mostly 8-bit. Here is a brief description of each< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > register:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > PC Program Counter< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This register points the address from which the next instruction< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > byte (opcode or parameter) will be fetched. Unlike other< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > registers, this one is 16 bits in length. The low and high 8-bit< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > halves of the register are called PCL and PCH, respectively. The< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Program Counter may be read by pushing its value on the stack.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This can be done either by jumping to a subroutine or by causing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > an interrupt.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > S Stack pointer< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The NMOS 65xx processors have 256 bytes of stack memory, ranging< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > from $0100 to $01FF. The S register is a 8-bit offset to the stack< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > page. In other words, whenever anything is being pushed on the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > stack, it will be stored to the address $0100+S.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The Stack pointer can be read and written by transfering its value< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to or from the index register X (see below) with the TSX and TXS< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instructions.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > P Processor status< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This 8-bit register stores the state of the processor. The bits in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > this register are called flags. Most of the flags have something< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to do with arithmetic operations.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The P register can be read by pushing it on the stack (with PHP or< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > by causing an interrupt). If you only need to read one flag, you< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > can use the branch instructions. Setting the flags is possible by< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > pulling the P register from stack or by using the flag set or< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > clear instructions.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Following is a list of the flags, starting from the 8th bit of the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > P register (bit 7, value $80):< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > N Negative flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This flag will be set after any arithmetic operations< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (when any of the registers A, X or Y is being loaded< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > with a value). Generally, the N flag will be copied from< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the topmost bit of the register being loaded.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Note that TXS (Transfer X to S) is not an arithmetic< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operation. Also note that the BIT instruction affects< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the Negative flag just like arithmetic operations.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Finally, the Negative flag behaves differently in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Decimal operations (see description below).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > V oVerflow flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Like the Negative flag, this flag is intended to be used< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > with 8-bit signed integer numbers. The flag will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > affected by addition and subtraction, the instructions< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > PLP, CLV and BIT, and the hardware signal -SO. Note that< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > there is no SEV instruction, even though the MOS< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > engineers loved to use East European abbreviations, like< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > DDR (Deutsche Demokratische Republik vs. Data Direction< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Register). (The Russian abbreviation for their former< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > trade association COMECON is SEV.) The -SO (Set< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Overflow) signal is available on some processors, at< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > least the 6502, to set the V flag. This enables response< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to an I/O activity in equal or less than three clock< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > cycles when using a BVC instruction branching to itself< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ($50 $FE).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The CLV instruction clears the V flag, and the PLP and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > BIT instructions copy the flag value from the bit 6 of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the topmost stack entry or from memory.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > After a binary addition or subtraction, the V flag will< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > be set on a sign overflow, cleared otherwise. What is a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > sign overflow? For instance, if you are trying to add< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 123 and 45 together, the result (168) does not fit in a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 8-bit signed integer (upper limit 127 and lower limit< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > -128). Similarly, adding -123 to -45 causes the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > overflow, just like subtracting -45 from 123 or 123 from< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > -45 would do.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Like the N flag, the V flag will not be set as expected< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > in the Decimal mode. Later in this document is a precise< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operation description.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > A common misbelief is that the V flag could only be set< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > by arithmetic operations, not cleared.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 1 unused flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > To the current knowledge, this flag is always 1.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > B Break flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This flag is used to distinguish software (BRK)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > interrupts from hardware interrupts (IRQ or NMI). The B< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > flag is always set except when the P register is being< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > pushed on stack when jumping to an interrupt routine to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > process only a hardware interrupt.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The official NMOS 65xx documentation claims that the BRK< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instruction could only cause a jump to the IRQ vector< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ($FFFE). However, if an NMI interrupt occurs while< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > executing a BRK instruction, the processor will jump to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the NMI vector ($FFFA), and the P register will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > pushed on the stack with the B flag set.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > D Decimal mode flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This flag is used to select the (Binary Coded) Decimal< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > mode for addition and subtraction. In most applications,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the flag is zero.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The Decimal mode has many oddities, and it operates< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > differently on CMOS processors. See the description of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the ADC, SBC and ARR instructions below.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > I Interrupt disable flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This flag can be used to prevent the processor from< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > jumping to the IRQ handler vector ($FFFE) whenever the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > hardware line -IRQ is active. The flag will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > automatically set after taking an interrupt, so that the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > processor would not keep jumping to the interrupt< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > routine if the -IRQ signal remains low for several clock< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > cycles.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Z Zero flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The Zero flag will be affected in the same cases than< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the Negative flag. Generally, it will be set if an< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > arithmetic register is being loaded with the value zero,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and cleared otherwise. The flag will behave differently< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > in Decimal operations.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > C Carry flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This flag is used in additions, subtractions,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > comparisons and bit rotations. In additions and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > subtractions, it acts as a 9th bit and lets you to chain< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operations to calculate with bigger than 8-bit numbers.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > When subtracting, the Carry flag is the negative of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Borrow: if an overflow occurs, the flag will be clear,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > otherwise set. Comparisons are a special case of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > subtraction: they assume Carry flag set and Decimal flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > clear, and do not store the result of the subtraction< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > anywhere.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > There are four kinds of bit rotations. All of them store< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the bit that is being rotated off to the Carry flag. The< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > left shifting instructions are ROL and ASL. ROL copies< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the initial Carry flag to the lowmost bit of the byte;< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ASL always clears it. Similarly, the ROR and LSR< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instructions shift to the right.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > A Accumulator< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The accumulator is the main register for arithmetic and logic< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operations. Unlike the index registers X and Y, it has a direct< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > connection to the Arithmetic and Logic Unit (ALU). This is why< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > many operations are only available for the accumulator, not the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > index registers.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > X Index register X< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This is the main register for addressing data with indices. It has< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > a special addressing mode, indexed indirect, which lets you to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > have a vector table on the zero page.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Y Index register Y< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The Y register has the least operations available. On the other< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > hand, only it has the indirect indexed addressing mode that< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > enables access to any memory place without having to use< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > self-modifying code.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510/8502 Undocumented Commands< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > -- A brief explanation about what may happen while using don't care states.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > ANE $8B A = (A | #$EE) & X & #byte< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > same as< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A = ((A & #$11 & X) | ( #$EE & X)) & #byte< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > In real 6510/8502 the internal parameter #$11< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > may occasionally be #$10, #$01 or even #$00.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This occurs when the video chip starts DMA< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > between the opcode fetch and the parameter fetch< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > of the instruction. The value probably depends< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > on the data that was left on the bus by the VIC-II.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > LXA $AB C=Lehti: A = X = ANE< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Alternate: A = X = (A & #byte)< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > TXA and TAX have to be responsible for these.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > SHA $93,$9F Store (A & X & (ADDR_HI + 1))< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SHX $9E Store (X & (ADDR_HI + 1))< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SHY $9C Store (Y & (ADDR_HI + 1))< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SHS $9B SHA and TXS, where X is replaced by (A & X).< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Note: The value to be stored is copied also< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to ADDR_HI if page boundary is crossed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > SBX $CB Carry and Decimal flags are ignored but the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Carry flag will be set in substraction. This< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > is due to the CMP command, which is executed< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instead of the real SBC.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ARR $6B This instruction first performs an AND< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > between the accumulator and the immediate< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > parameter, then it shifts the accumulator to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the right. However, this is not the whole< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > truth. See the description below.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Many undocumented commands do not use AND between registers, the CPU< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > just throws the bytes to a bus simultaneously and lets the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > open-collector drivers perform the AND. I.e. the command called 'SAX',< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > which is in the STORE section (opcodes $A0...$BF), stores the result< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > of (A & X) by this way.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > More fortunate is its opposite, 'LAX' which just loads a byte< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > simultaneously into both A and X.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > $6B ARR< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This instruction seems to be a harmless combination of AND and ROR at< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > first sight, but it turns out that it affects the V flag and also has< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > a special kind of decimal mode. This is because the instruction has< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > inherited some properties of the ADC instruction ($69) in addition to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the ROR ($6A).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > In Binary mode (D flag clear), the instruction effectively does an AND< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > between the accumulator and the immediate parameter, and then shifts< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the accumulator to the right, copying the C flag to the 8th bit. It< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > sets the Negative and Zero flags just like the ROR would. The ADC code< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > shows up in the Carry and oVerflow flags. The C flag will be copied< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > from the bit 6 of the result (which doesn't seem too logical), and the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > V flag is the result of an Exclusive OR operation between the bit 6< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and the bit 5 of the result. This makes sense, since the V flag will< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > be normally set by an Exclusive OR, too.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > In Decimal mode (D flag set), the ARR instruction first performs the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > AND and ROR, just like in Binary mode. The N flag will be copied from< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the initial C flag, and the Z flag will be set according to the ROR< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > result, as expected. The V flag will be set if the bit 6 of the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > accumulator changed its state between the AND and the ROR, cleared< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > otherwise.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Now comes the funny part. If the low nybble of the AND result,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > incremented by its lowmost bit, is greater than 5, the low nybble in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the ROR result will be incremented by 6. The low nybble may overflow< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > as a consequence of this BCD fixup, but the high nybble won't be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > adjusted. The high nybble will be BCD fixed in a similar way. If the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > high nybble of the AND result, incremented by its lowmost bit, is< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > greater than 5, the high nybble in the ROR result will be incremented< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > by 6, and the Carry flag will be set. Otherwise the C flag will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > cleared.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > To help you understand this description, here is a C routine that< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > illustrates the ARR operation in Decimal mode:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > unsigned< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A, /* Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL, /* low nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH, /* high nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > C, /* Carry flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z, /* Zero flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V, /* oVerflow flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N, /* Negative flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > t, /* temporary value */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > s; /* value to be ARRed with Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > t = A & s; /* Perform the AND. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH = t > > 4; /* Separate the high */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL = t & 15; /* and low nybbles. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N = C; /* Set the N and */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z = !(A = (t > > 1) | (C < < 7)); /* Z flags traditionally */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V = (t ^ A) & 64; /* and V flag in a weird way. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (AL + (AL & 1) > 5) /* BCD "fixup" for low nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A = (A & 0xF0) | ((A + 6) & 0xF);< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (C = AH + (AH & 1) > 5) /* Set the Carry flag. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A = (A + 0x60) & 0xFF; /* BCD "fixup" for high nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > $CB SBX X < - (A & X) - Immediate< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > The 'SBX' ($CB) may seem to be very complex operation, even though it< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > is a combination of the subtraction of accumulator and parameter, as< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > in the 'CMP' instruction, and the command 'DEX'. As a result, both A< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and X are connected to ALU but only the subtraction takes place. Since< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the comparison logic was used, the result of subtraction should be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > normally ignored, but the 'DEX' now happily stores to X the value of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (A & X) - Immediate. That is why this instruction does not have any< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > decimal mode, and it does not affect the V flag. Also Carry flag will< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > be ignored in the subtraction but set according to the result.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Proof:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 644 vsbx< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`0@9$,D'GL(H-#,IJC(U-JS"*#0T*:HR-@```*D`H#V1*Z`_D2N@09$KJ0> %< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M^QBE^VEZJ+$KH#F1*ZD`2"BI`*(`RP`(:-B@.5$K*4#P`E@`H#VQ*SAI`)$K< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > JD-Z@/[$K:0"1*Y#4J2X@TO\XH$& Q*VD`D2N0Q,;[$+188/_^]_:_OK> V< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > `< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > begin 644 sbx< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`0@9$,D'GL(H-#,IJC(U-JS"*#0T*:HR-@```'BI`*!-D2N@3Y$KH%& 1*ZD#< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > MA?L8I?M*2)`#J1@LJ3B@29$K:$J0`ZGX+*G8R)$K& /BXJ?2B8\L)AOP(:(7]< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > MV#B@3;$KH$\Q*Z!1\2L(1?SP`0!H1?TIM]#XH$VQ*SAI`)$KD,N@3[$K:0"1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 9*Y#!J2X@TO\XH%& Q*VD`D2N0L< ;[$))88-#X< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > `< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > These test programs show if your machine is compatible with ours< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > regarding the opcode $CB. The first test, vsbx, proves that SBX does< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > not affect the V flag. The latter one, sbx, proves the rest of our< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > theory. The vsbx test tests 33554432 SBX combinations (16777216< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > different A, X and Immediate combinations, and two different V flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > states), and the sbx test doubles that amount (16777216*4 D and C flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > combinations). Both tests have run successfully on a C64 and a Vic20.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > They ought to run on C16, +4 and the PET series as well. The tests< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > stop with BRK, if the opcode $CB does not work as expected. Successful< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operation ends in RTS. As the tests are very slow, they print dots on< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the screen while running so that you know that the machine has not< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > jammed. On computers running at 1 MHz, the first test prints< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > approximately one dot every four seconds and a total of 2048 dots,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > whereas the second one prints half that amount, one dot every seven< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > seconds.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > If the tests fail on your machine, please let us know your processor's< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > part number and revision. If possible, save the executable (after it< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > has stopped with BRK) under another name and send it to us so that we< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > know at which stage the program stopped.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The following program is a Commodore 64 executable that Marko M"akel"a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > developed when trying to find out how the V flag is affected by SBX.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (It was believed that the SBX affects the flag in a weird way, and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > this program shows how SBX sets the flag differently from SBC.) You< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > may find the subroutine at $C150 useful when researching other< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > undocumented instructions' flags. Run the program in a machine< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > language monitor, as it makes use of the BRK instruction. The result< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > tables will be written on pages $C2 and $C3.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 644 sbx-c100< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`,%XH`",#L& ,$,& ,$L& XJ8*B@LL7AOL(:(7\N#BM#L$M$,'M$L$(Q?OP`B@`< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M:$7\\`,@4,'N#L'0U.X0P=#/SB#0[A+!T,< ``````````````)BJ\!> M#L$M< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > L$,'=_\'0":T2P=W_PM`!8,K0Z:T.P2T0P9D`PID`!*T2P9D`PYD`!< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Other undocumented instructions usually cause two preceding opcodes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > being executed. However 'NOP' seems to completely disappear from 'SBC'< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > code $EB.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The most difficult to comprehend are the rest of the instructions< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > located on the '$0B' line.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > All the instructions located at the positive (left) side of this line< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > should rotate either memory or the accumulator, but the addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > mode turns out to be immediate! No problem. Just read the operand, let< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > it be ANDed with the accumulator and finally use accumulator< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > addressing mode for the instructions above them.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > RELIGION_MODE_ON< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > /* This part of the document is not accurate. You can< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > read it as a fairy tale, but do not count on it when< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > performing your own measurements. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The rest two instructions on the same line, called 'ANE' and 'LXA'< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ($8B and $AB respectively) often give quite unpredictable results.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > However, the most usual operation is to store ((A | #$ee) & X & #$nn)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to accumulator. Note that this does not work reliably in a real 64!< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > In the Commodore 128 the opcode $8B uses values 8C, CC, EE, and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > occasionally 0C and 8E for the OR instead of EE,EF,FE and FF used in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the C64. With a C128 running at 2 MHz #$EE is always used. Opcode $AB< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > does not cause this OR taking place on 8502 while 6510 always performs< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > it. Note that this behaviour depends on processor and/or video chip< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > revision.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Let's take a closer look at $8B (6510).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > A < - X & D & (A | VAL)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > where VAL comes from this table:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > X high D high D low VAL< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > even even --- $EE (1)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > even odd --- $EE< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > odd even --- $EE< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > odd odd 0 $EE< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > odd odd not 0 $FE (2)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (1) If the bottom 2 bits of A are both 1, then the LSB of the result may< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > be 0. The values of X and D are different every time I run the test.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > This appears to be very rare.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (2) VAL is $FE most of the time. Sometimes it is $EE - it seems to be random,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > not related to any of the data. This is much more common than (1).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > In decimal mode, VAL is usually $FE.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Two different functions have been discovered for LAX, opcode $AB. One< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > is A = X = ANE (see above) and the other, encountered with 6510 and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 8502, is less complicated A = X = (A & #byte). However, according to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > what is reported, the version altering only the lowest bits of each< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > nybble seems to be more common.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > What happens, is that $AB loads a value into both A and X, ANDing the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > low bit of each nybble with the corresponding bit of the old< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > A. However, there are exceptions. Sometimes the low bit is cleared< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > even when A contains a '1', and sometimes other bits are cleared. The< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > exceptions seem random (they change every time I run the test). Oops -< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > that was in decimal mode. Much the same with D=0.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > What causes the randomness? Probably it is that it is marginal logic< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > levels - when too much wired-anding goes on, some of the signals get< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > very close to the threshold. Perhaps we're seeing some of them step< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > over it. The low bit of each nybble is special, since it has to cope< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > with carry differently (remember decimal mode). We never see a '0'< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > turn into a '1'.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Since these instructions are unpredictable, they should not be used.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > There is still very strange instruction left, the one named SHA/X/Y,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > which is the only one with only indexed addressing modes. Actually,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the commands 'SHA', 'SHX' and 'SHY' are generated by the indexing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > algorithm.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > While using indexed addressing, effective address for page boundary< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > crossing is calculated as soon as possible so it does not slow down< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > operation. As a result, in the case of SHA/X/Y, the address and data< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > are processed at the same time making AND between them to take place.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Thus, the value to be stored by SAX, for example, is in fact (A & X & < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (ADDR_HI + 1)). On page boundary crossing the same value is copied< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > also to high byte of the effective address.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > RELIGION_MODE_OFF< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Register selection for load and store< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > bit1 bit0 A X Y< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 0 0 x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 0 1 x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 0 x< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 1 x x< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > So, A and X are selected by bits 1 and 0 respectively, while< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ~(bit1|bit0) enables Y.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Indexing is determined by bit4, even in relative addressing mode,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > which is one kind of indexing.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Lines containing opcodes xxx000x1 (01 and 03) are treated as absolute< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > after the effective address has been loaded into CPU.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Zeropage,y and Absolute,y (codes 10x1 x11x) are distinquished by bit5.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Decimal mode in NMOS 6500 series< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Most sources claim that the NMOS 6500 series sets the N, V and Z< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > flags unpredictably when performing addition or subtraction in decimal< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > mode. Of course, this is not true. While testing how the flags are< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > set, I also wanted to see what happens if you use illegal BCD values.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > ADC works in Decimal mode in a quite complicated way. It is amazing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > how it can do that all in a single cycle. Here's a C code version of< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the instruction:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > unsigned< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A, /* Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL, /* low nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH, /* high nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > C, /* Carry flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z, /* Zero flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V, /* oVerflow flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N, /* Negative flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > s; /* value to be added to Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL = (A & 15) + (s & 15) + C; /* Calculate the lower nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH = (A > > 4) + (s > > 4) + (AL > 15); /* Calculate the upper nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (AL > 9) AL += 6; /* BCD fixup for lower nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z = ((A + s + C) & 255 != 0); /* Zero flag is set just< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > like in Binary mode. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > /* Negative and Overflow flags are set with the same logic than in< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Binary mode, but after fixing the lower nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N = (AH & 8 != 0);< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V = ((AH < < 4) ^ A) & 128 & & !((A ^ s) & 128);< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (AH > 9) AH += 6; /* BCD fixup for upper nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > /* Carry is the only flag set after fixing the result. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > C = (AH > 15);< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A = ((AH < < 4) | (AL & 15)) & 255;< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The C flag is set as the quiche eaters expect, but the N and V flags< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > are set after fixing the lower nybble but before fixing the upper one.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > They use the same logic than binary mode ADC. The Z flag is set before< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > any BCD fixup, so the D flag does not have any influence on it.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Proof: The following test program tests all 131072 ADC combinations in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Decimal mode, and aborts with BRK if anything breaks this theory.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > If everything goes well, it ends in RTS.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 600 dadc< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M 0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@ 'BI& * A/N$_$B@+)$KH(V1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M*Q@(I?PI#X7]I?LI#V7]R0J0 FD%J"D/A?VE^RGP9?PI\ C $) ":0^JL @H< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ML ?)H) & ""@X:5\X!?V%_0AH*3W@ ! ""8"HBD7[$ JE^T7\, 28"4"H**7[< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M9?S0!)@) J@8N/BE^V7\V A%_= G:(3]1?W0(.;[T(?F_-"#:$D8\ )88*D=< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 0& & 4KA?NI & 4LA?RI.& S[ A%< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > All programs in this chapter have been successfully tested on a Vic20< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and a Commodore 64 and a Commodore 128D in C64 mode. They should run on< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > C16, +4 and on the PET series as well. If not, please report the problem< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to Marko M"akel"a. Each test in this chapter should run in less than a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > minute at 1 MHz.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > SBC is much easier. Just like CMP, its flags are not affected by< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the D flag.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Proof:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 600 dsbc-cmp-flags< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M 0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@ 'B@ (3[A/RB XH8:66HL2N@< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M09$KH$R1*XII::BQ*Z!%D2N@4)$K^#BXI?OE_-@(:(7].+BE^^7\"& A%_? !< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 .;[T./F_-#?RA"_8!@X& #CEY< 7%< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The only difference in SBC's operation in decimal mode from binary mode< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > is the result-fixup:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > unsigned< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A, /* Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL, /* low nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH, /* high nybble of accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > C, /* Carry flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z, /* Zero flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V, /* oVerflow flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N, /* Negative flag */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > s; /* value to be added to Accumulator */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AL = (A & 15) - (s & 15) - !C; /* Calculate the lower nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (AL & 16) AL -= 6; /* BCD fixup for lower nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AH = (A > > 4) - (s > > 4) - (AL & 16); /* Calculate the upper nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > if (AH & 16) AH -= 6; /* BCD fixup for upper nybble. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > /* The flags are set just like in Binary mode. */< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > C = (A - s - !C) & 256 != 0;< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Z = (A - s - !C) & 255 != 0;< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > V = ((A - s - !C) ^ s) & 128 & & (A ^ s) & 128;< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > N = (A - s - !C) & 128 != 0;< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > A = ((AH < < 4) | (AL & 15)) & 255;< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > Again Z flag is set before any BCD fixup. The N and V flags are set< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > at any time before fixing the high nybble. The C flag may be set in any< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > phase.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Decimal subtraction is easier than decimal addition, as you have to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > make the BCD fixup only when a nybble overflows. In decimal addition,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > you had to verify if the nybble was greater than 9. The processor has< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > an internal "half carry" flag for the lower nybble, used to trigger< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the BCD fixup. When calculating with legal BCD values, the lower nybble< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > cannot overflow again when fixing it.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > So, the processor does not handle overflows while performing the fixup.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Similarly, the BCD fixup occurs in the high nybble only if the value< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > overflows, i.e. when the C flag will be cleared.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Because SBC's flags are not affected by the Decimal mode flag, you< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > could guess that CMP uses the SBC logic, only setting the C flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > first. But the SBX instruction shows that CMP also temporarily clears< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the D flag, although it is totally unnecessary.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The following program, which tests SBC's result and flags,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > contains the 6502 version of the pseudo code example above.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 600 dsbc< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M 0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@ 'BI& * A/N$_$B@+)$KH':1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M*S@(I?PI#X7]I?LI#^7]L /I!1@I#ZBE_"GPA?VE^RGP"#CE_2GPL KI7RBP< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M#ND/.+ )*+ & Z0^P NE?A/T%_87]*+BE^^7\"& BH.+CXI?OE_-@(1?W0FVB$< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 8_47]T)3F^]"> YOS0FFA)& - $J3C0B%A@< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Obviously the undocumented instructions RRA (ROR+ADC) and ISB< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (INC+SBC) have inherited also the decimal operation from the official< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instructions ADC and SBC. The program droradc proves this statement< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > for ROR, and the dincsbc test proves this for ISB. Finally,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > dincsbc-deccmp proves that ISB's and DCP's (DEC+CMP) flags are not< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > affected by the D flag.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > begin 644 droradc< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@```'BI& *``A/N$_$B@+)$KH(V1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M*S@(I?PI#X7]I?LI#V7]R0J0`FD%J"D/A?VE^RGP9?PI\`C`$)`":0^JL`@H< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ML`?)H)`& ""@X:5\X!?V%_0AH*3W@`!`""8"HBD7[$`JE^T7\,`28"4"H**7[< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M9?S0!)@)`J@XN/BE^R;\9_S8"$7]T"=HA/U%_=`@YOO0A> ;\T(%H21CP`EA@< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2J1T892N%^ZD`92R%_*DX;/L`< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > `< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > begin 644 dincsbc< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@```'BI& *``A/N$_$B@+)$KH':1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M*S@(I?PI#X7]I?LI#^7]L`/I!1@I#ZBE_"GPA?VE^RGP"#CE_2GPL`KI7RBP< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M#ND/.+`)*+`& Z0^P`NE?A/T%_87]*+BE^^7\"& BH.+CXI?O& _.?\V`A%_="9< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ::(3]1?W0DN;[T)SF_-"8:$D8T`2I.-"& 6& #\< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > `< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > begin 644 dincsbc-deccmp< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M`0@9",D'GL(H-#,IJC(U-JS"*#0T*:HR-@```'B@`(3[A/RB`XH8:7> HL2N@< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > M3Y$KH%R1*XII> ZBQ*Z!3D2N@8)$KBFE_J+$KH%61*Z!BD2OX.+BE^^;\Q_S8< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > L"& B%_3BXI?OF_,?\"& A%_?`!`.;[T-_F_-#;RA"M8!@X& #CFYL;& Q\?GYP#8< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > `< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > end< / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 features< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o PHP always pushes the Break (B) flag as a `1' to the stack.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Jukka Tapanim"aki claimed in C=lehti issue 3/89, on page 27 that the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > processor makes a logical OR between the status register's bit 4< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and the bit 8 of the stack pointer register (which is always 1).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > He did not give any reasons for this argument, and has refused to clarify< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > it afterwards. Well, this was not the only error in his article...< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o Indirect addressing modes do not handle page boundary crossing at all.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > When the parameter's low byte is $FF, the effective address wraps< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > around and the CPU fetches high byte from $xx00 instead of $xx00+$0100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > E.g. JMP ($01FF) fetches PCL from $01FF and PCH from $0100,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > and LDA ($FF),Y fetches the base address from $FF and $00.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o Indexed zero page addressing modes never fix the page address on< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > crossing the zero page boundary.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > E.g. LDX #$01 : LDA ($FF,X) loads the effective address from $00 and $01.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o The processor always fetches the byte following a relative branch< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instruction. If the branch is taken, the processor reads then the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > opcode from the destination address. If page boundary is crossed, it< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > first reads a byte from the old page from a location that is bigger< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > or smaller than the correct address by one page.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o If you cross a page boundary in any other indexed mode,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the processor reads an incorrect location first, a location that is< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > smaller by one page.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o Read-Modify-Write instructions write unmodified data, then modified< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (so INC effectively does LDX loc;STX loc;INX;STX loc)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o -RDY is ignored during writes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (This is why you must wait 3 cycles before doing any DMA --< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the maximum number of consecutive writes is 3, which occurs< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > during interrupts except -RESET.)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o Some undefined opcodes may give really unpredictable results.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > o All registers except the Program Counter remain unmodified after -RESET.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (This is why you must preset D and I flags in the RESET handler.)< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Different CPU types< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The Rockwell data booklet 29651N52 (technical information about R65C00< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > microprocessors, dated October 1984), lists the following differences between< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS R6502 microprocessor and CMOS R65C00 family:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 1. Indexed addressing across page boundary.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Extra read of invalid address.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: Extra read of last instruction byte.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 2. Execution of invalid op codes.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Some terminate only by reset. Results are undefined.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: All are NOPs (reserved for future use).< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 3. Jump indirect, operand = XXFF.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Page address does not increment.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: Page address increments and adds one additional cycle.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 4. Read/modify/write instructions at effective address.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: One read and two write cycles.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: Two read and one write cycle.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 5. Decimal flag.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Indeterminate after reset.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: Initialized to binary mode (D=0) after reset and interrupts.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6. Flags after decimal operation.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Invalid N, V and Z flags.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: Valid flag adds one additional cycle.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 7. Interrupt after fetch of BRK instruction.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMOS: Interrupt vector is loaded, BRK vector is ignored.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > CMOS: BRK is executed, then interrupt is executed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > 6510 Instruction Timing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The NMOS 6500 series processors always perform at least two reads< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > for each instruction. In addition to the operation code (opcode), they< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > fetch the next byte. This is quite efficient, as most instructions are< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > two or three bytes long.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The processors also use a sort of pipelining. If an instruction does< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > not store data in memory on its last cycle, the processor can fetch< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the opcode of the next instruction while executing the last cycle. For< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instance, the instruction EOR #$FF truly takes three cycles. On the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > first cycle, the opcode $49 will be fetched. During the second cycle< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the processor decodes the opcode and fetches the parameter #$FF. On< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the third cycle, the processor will perform the operation and store< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the result to accumulator, but simultaneously it fetches the opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > for the next instruction. This is why the instruction effectively< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > takes only two cycles.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The following tables show what happens on the bus while executing< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > different kinds of instructions.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Interrupts< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > NMI and IRQ both take 7 cycles. Their timing diagram is much like< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > BRK's (see below). IRQ will be executed only when the I flag is< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > clear. IRQ and BRK both set the I flag, whereas the NMI does not< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > affect its state.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The processor will usually wait for the current instruction to< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > complete before executing the interrupt sequence. To process the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > interrupt before the next instruction, the interrupt must occur< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > before the last cycle of the current instruction.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > There is one exception to this rule: the BRK instruction. If a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > hardware interrupt (NMI or IRQ) occurs before the fourth (flags< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > saving) cycle of BRK, the BRK instruction will be skipped, and< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the processor will jump to the hardware interrupt vector. This< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > sequence will always take 7 cycles.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > You do not completely lose the BRK interrupt, the B flag will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > set in the pushed status register if a BRK instruction gets< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > interrupted. When BRK and IRQ occur at the same time, this does< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > not cause any problems, as your program will consider it as a< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > BRK, and the IRQ would occur again after the processor returned< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > from your BRK routine, unless you cleared the interrupt source in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > your BRK handler. But the simultaneous occurrence of NMI and BRK< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > is far more fatal. If you do not check the B flag in the NMI< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > routine and subtract two from the return address when needed, the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > BRK instruction will be skipped.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > If the NMI and IRQ interrupts overlap each other (one interrupt< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > occurs before fetching the interrupt vector for the other< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > interrupt), the processor will most probably jump to the NMI< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > vector in every case, and then jump to the IRQ vector after< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > processing the first instruction of the NMI handler. This has not< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > been measured yet, but the IRQ is very similar to BRK, and many< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > sources state that the NMI has higher priority than IRQ. However,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > it might be that the processor takes the interrupt that comes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > later, i.e. you could lose an NMI interrupt if an IRQ occurred in< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > four cycles after it.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > After finishing the interrupt sequence, the processor will start< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > to execute the first instruction of the interrupt routine. This< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > proves that the processor uses a sort of pipelining: it finishes< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > the current instruction (or interrupt sequence) while reading the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > opcode of the next instruction.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > RESET does not push program counter on stack, and it lasts< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > probably 6 cycles after deactivating the signal. Like NMI, RESET< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > preserves all registers except PC.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Instructions accessing the stack< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > BRK< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away),< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S W push PCH on stack (with B flag set), decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 $0100,S W push PCL on stack, decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 $0100,S W push P on stack, decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 $FFFE R fetch PCL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 7 $FFFF R fetch PCH< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > RTI< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S R increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 $0100,S R pull P from stack, increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 $0100,S R pull PCL from stack, increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 $0100,S R pull PCH from stack< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > RTS< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S R increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 $0100,S R pull PCL from stack, increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 $0100,S R pull PCH from stack< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 PC R increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > PHA, PHP< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S W push register on stack, decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > PLA, PLP< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S R increment S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 $0100,S R pull register from stack< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > JSR< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -------------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low address byte, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 $0100,S R internal operation (predecrement S?)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 $0100,S W push PCH on stack, decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 $0100,S W push PCL on stack, decrement S< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 PC R copy low address byte to PCL, fetch high address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > byte to PCH< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Accumulator or implied addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -----------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R read next instruction byte (and throw it away)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Immediate addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch value, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Absolute addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > JMP< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- -------------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low address byte, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R copy low address byte to PCL, fetch high address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > byte to PCH< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LAX, NOP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (ASL, LSR, ROL, ROR, INC, DEC,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, STX, STY, SAX)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address W write register to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Zero page addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LAX, NOP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (ASL, LSR, ROL, ROR, INC, DEC,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, STX, STY, SAX)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address W write register to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Zero page indexed addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LAX, NOP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address R read from address, add index register to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+I* R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: I denotes either index register (X or Y).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address is always zero,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. page boundary crossings are not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (ASL, LSR, ROL, ROR, INC, DEC,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ---------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address R read from address, add index register X to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+X* R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+X* W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address+X* W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Note: * The high byte of the effective address is always zero,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. page boundary crossings are not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, STX, STY, SAX)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- -------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 address R read from address, add index register to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+I* W write to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: I denotes either index register (X or Y).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address is always zero,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. page boundary crossings are not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Absolute indexed addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LAX, LAE, SHS, NOP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add index register to low address byte,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+I* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix the high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5+ address+I R re-read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: I denotes either index register (X or Y).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > + This cycle will be executed only if the effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > was invalid during cycle #4, i.e. page boundary was crossed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (ASL, LSR, ROL, ROR, INC, DEC,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add index register X to low address byte,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+X* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix the high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+X R re-read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address+X W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 7 address+X W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, STX, STY, SHA, SHX, SHY)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch low byte of address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch high byte of address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add index register to low address byte,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 address+I* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix the high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+I W write to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: I denotes either index register (X or Y).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100. Because< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > the processor cannot undo a write to an invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > address, it always reads from the address first.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Relative addressing (BCC, BCS, BNE, BEQ, BPL, BMI, BVC, BVS)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ---------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch operand, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R Fetch opcode of next instruction,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > If branch is taken, add operand to PCL.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Otherwise increment PC.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4+ PC* R Fetch opcode of next instruction.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Fix PCH. If it did not change, increment PC.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5! PC R Fetch opcode of next instruction,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > increment PC.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: The opcode fetch of the next instruction is included to< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > this diagram for illustration purposes. When determining< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > real execution times, remember to subtract the last< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > cycle.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of Program Counter (PCH) may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller or bigger by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > + If branch is taken, this cycle will be executed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ! If branch occurs to different page, this cycle will be< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > executed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Indexed indirect addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, ORA, EOR, AND, ADC, CMP, SBC, LAX)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R read from the address, add X to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+X R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 pointer+X+1 R fetch effective address high< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Note: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R read from the address, add X to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+X R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 pointer+X+1 R fetch effective address high< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 7 address W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 8 address W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Note: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, SAX)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R read from the address, add X to it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+X R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 pointer+X+1 R fetch effective address high< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address W write to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Note: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Indirect indexed addressing< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read instructions (LDA, EOR, AND, ORA, ADC, SBC, CMP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+1 R fetch effective address high,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add Y to low byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+Y* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6+ address+Y R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > + This cycle will be executed only if the effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > was invalid during cycle #5, i.e. page boundary was crossed.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Read-Modify-Write instructions (SLO, SRE, RLA, RRA, ISB, DCP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+1 R fetch effective address high,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add Y to low byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+Y* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address+Y R read from effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 7 address+Y W write the value back to effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > and do the operation on it< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 8 address+Y W write the new value to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Write instructions (STA, SHA)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ----------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 pointer R fetch effective address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer+1 R fetch effective address high,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > add Y to low byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 address+Y* R read from effective address,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > fix high byte of effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 address+Y W write to effective address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Notes: The effective address is always fetched from zero page,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > i.e. the zero page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > * The high byte of the effective address may be invalid< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > at this time, i.e. it may be smaller by $100.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Absolute indirect addressing (JMP)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- --------- --- ------------------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 PC R fetch opcode, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 PC R fetch pointer address low, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 PC R fetch pointer address high, increment PC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 pointer R fetch low address to latch< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 pointer+1* R fetch PCH, copy latch to PCL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Note: * The PCH will always be fetched from the same page< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > than PCL, i.e. page boundary crossing is not handled.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > How Real Programmers Acknowledge Interrupts< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > With RMW instructions:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; beginning of combined raster/timer interrupt routine< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LSR $D019 ; clear VIC interrupts, read raster interrupt flag to C< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > BCS raster ; jump if VIC caused an interrupt< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ... ; timer interrupt routine< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of LSR $D019:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 4E PC R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 19 PC+1 R fetch address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 D0 PC+2 R fetch address high< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 xx $D019 R read memory< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 xx $D019 W write the value back, rotate right< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 6 xx/2 $D019 W write the new value back< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > The 5th cycle acknowledges the interrupt by writing the same< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > value back. If only raster interrupts are used, the 6th cycle< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > has no effect on the VIC. (It might acknowledge also some< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > other interrupts.)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > With indexed addressing:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; acknowledge interrupts to both CIAs< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDX #$10< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DCFD,X< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of LDA $DCFD,X:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 BD PC R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 FD PC+1 R fetch address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 DC PC+2 R fetch address high, add X to address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 xx $DC0D R read from address, fix high byte of address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 yy $DD0D R read from right address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; acknowledge interrupts to CIA 2< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDX #$10< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DDFD,X< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of STA $DDFD,X:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 9D PC R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 FD PC+1 R fetch address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 DC PC+2 R fetch address high, add X to address low< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 xx $DD0D R read from address, fix high byte of address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 5 ac $DE0D W write to right address< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > With branch instructions:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; acknowledge interrupts to CIA 2< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$00 ; clear N flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > JMP $DD0A< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DD0A BPL $DC9D ; branch< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DC9D BRK ; return< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > You need the following preparations to initialize the CIA registers:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$91 ; argument of BPL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0B< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$10 ; BPL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0A< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD08 ; load the ToD values from the latches< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0B ; freeze the ToD display< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$7F< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DC0D ; assure that $DC0D is $00< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of BPL $DC9D:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 10 $DD0A R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 91 $DD0B R fetch argument< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 xx $DD0C R fetch opcode, add argument to PCL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 yy $DD9D R fetch opcode, fix PCH< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ( 5 00 $DC9D R fetch opcode )< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; acknowledge interrupts to CIA 1< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LSR ; clear N flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > JMP $DCFA< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DCFA BPL $DD0D< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DD0D BRK< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; Again you need to set the ToD registers of CIA 1 and the< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; Interrupt Control Register of CIA 2 first.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of BPL $DD0D:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 10 $DCFA R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 11 $DCFB R fetch argument< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 xx $DCFC R fetch opcode, add argument to PCL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 yy $DC0D R fetch opcode, fix PCH< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ( 5 00 $DD0D R fetch opcode )< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; acknowledge interrupts to CIA 2 automagically< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; preparations< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$7F< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0D ; disable all interrupt sources of CIA2< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0E< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AND #$BE ; ensure that $DD0C remains constant< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0E ; and stop the timer< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$FD< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0C ; parameter of BPL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$10< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0B ; BPL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$40< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0A ; RTI/parameter of LSR< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$46< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD09 ; LSR< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD08 ; load the ToD values from the latches< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0B ; freeze the ToD display< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$09< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $0318< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$DD< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $0319 ; change NMI vector to $DD09< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$FF ; Try changing this instruction's operand< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD05 ; (see comment below).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$FF< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD04 ; set interrupt frequency to 1/65536 cycles< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0E< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AND #$80< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ORA #$11< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDX #$81< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STX $DD0D ; enable timer interrupt< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0E ; start timer< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$00 ; To see that the interrupts really occur,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $D011 ; use something like this and see how< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LOOP DEC $D020 ; changing the byte loaded to $DD05 from< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > BNE LOOP ; #$FF to #$0F changes the image.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > When an NMI occurs, the processor jumps to Kernal code, which jumps to< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ($0318), which points to the following routine:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DD09 LSR $40 ; clear N flag< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > BPL $DD0A ; Note: $DD0A contains RTI.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > Operational diagram of BPL $DD0A:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > # data address R/W description< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > --- ---- ------- --- ---------------------------------< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 1 10 $DD0B R fetch opcode< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 2 11 $DD0C R fetch argument< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 3 xx $DD0D R fetch opcode, add argument to PCL< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > 4 40 $DD0A R fetch opcode, (fix PCH)< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > With RTI:< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; the fastest possible interrupt handler in the 6500 family< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ; preparations< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > SEI< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $01 ; disable ROM and enable I/O< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AND #$FD< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ORA #$05< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $01< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$7F< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0D ; disable CIA 2's all interrupt sources< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0E< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AND #$BE ; ensure that $DD0C remains constant< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0E ; and stop the timer< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$40< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0C ; store RTI to $DD0C< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$0C< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $FFFA< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$DD< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $FFFB ; change NMI vector to $DD0C< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$FF ; Try changing this instruction's operand< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD05 ; (see comment below).< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$FF< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD04 ; set interrupt frequency to 1/65536 cycles< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA $DD0E< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > AND #$80< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > ORA #$11< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDX #$81< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STX $DD0D ; enable timer interrupt< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $DD0E ; start timer< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LDA #$00 ; To see that the interrupts really occur,< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > STA $D011 ; use something like this and see how< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > LOOP DEC $D020 ; changing the byte loaded to $DD05 from< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > BNE LOOP ; #$FF to #$0F changes the image.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > When an NMI occurs, the processor jumps to Kernal code, which< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > jumps to ($0318), which points to the following routine:< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > DD0C RTI< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > How on earth can this clear the interrupts? Remember, the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > processor always fetches two successive bytes for each< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instruction.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > A little more practical version of this is redirecting the NMI< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > (or IRQ) to your own routine, whose last instruction is JMP< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > $DD0C or JMP $DC0C. If you want to confuse more, change the 0< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > in the address to a hexadecimal digit different from the one< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > you used when writing the RTI.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > Or you can combine the latter two methods:< / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DD09 LSR $xx ; xx is any appropriate BCD value 00-59.< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > BPL $DCFC< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > DCFC RTI< / span > < / p >
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > This example acknowledges interrupts to both CIAs.< / span > < / p >
2022-02-04 01:16:06 +00:00
< p class = "rvps2" > < span class = "rvts60" > < br / > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps2" > < span class = "rvts6" > If you want to confuse the examiners of your code, you can use any< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > of these techniques. Although these examples use no undefined opcodes,< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > they do not necessarily run correctly on CMOS processors. However, the< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > RTI example should run on 65C02 and 65C816, and the latter branch< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > instruction example might work as well.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > The RMW instruction method has been used in some demos, others were< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > developed by Marko M"akel"a. His favourite is the automagical RTI< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > method, although it does not have any practical applications, except< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > for some time dependent data decryption routines for very complicated< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > copy protections.< / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
< p class = "rvps2" > < span class = "rvts6" > < br / > < / span > < / p >
2021-06-25 01:27:09 +00:00
< p class = "rvps2" > < span class = "rvts6" > < / span > < span class = "rvts6" > < / span > < / p >
2020-12-16 11:41:37 +00:00
< p class = "rvps4" style = "clear: both;" > < span class = "rvts18" > Created with the Personal Edition of HelpNDoc: < / span > < a class = "rvts19" href = "https://www.helpndoc.com/feature-tour/iphone-website-generation" > Easily create iPhone documentation< / a > < / p >
< / div >
< div id = "topic_footer" > < div id = "topic_footer_content" > 2020< / div > < / div >
< / div > <!-- /#topic - content -->
< / article >
< footer > < / footer >
< / div > <!-- /#main -->
< div class = "mask" data-toggle = "sm-nav-expanded" > < / div >
<!-- Modal -->
< div class = "modal fade" id = "hndModal" tabindex = "-1" role = "dialog" aria-labelledby = "hndModalLabel" >
< div class = "modal-dialog" role = "document" >
< div class = "modal-content" >
< div class = "modal-header" >
< button type = "button" class = "close" data-dismiss = "modal" aria-label = "Close" > < span aria-hidden = "true" > × < / span > < / button >
< h4 class = "modal-title" id = "hndModalLabel" > < / h4 >
< / div >
< div class = "modal-body" >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-primary modal-btn-close" data-dismiss = "modal" > Close< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Splitter -->
< div id = "hnd-splitter" style = "left: 250px" > < / div >
<!-- Scripts -->
< script src = "vendors/jquery-3.5.1/jquery.min.js" > < / script >
< script src = "vendors/bootstrap-3.4.1/js/bootstrap.min.js" > < / script >
< script src = "vendors/bootstrap-3.4.1/js/ie10-viewport-bug-workaround.js" > < / script >
< script src = "vendors/markjs-8.11.1/jquery.mark.min.js" > < / script >
< script src = "vendors/uri-1.19.2/uri.min.js" > < / script >
< script src = "vendors/imageMapResizer-1.0.10/imageMapResizer.min.js" > < / script >
< script src = "vendors/headroom-0.11.0/headroom.min.js" > < / script >
< script src = "vendors/jstree-3.3.10/jstree.min.js" > < / script >
< script src = "vendors/interactjs-1.9.22/interact.min.js" > < / script >
<!-- HelpNDoc scripts -->
< script src = "js/polyfill.object.min.js" > < / script >
< script src = "_translations.js" > < / script >
< script src = "js/hndsd.min.js" > < / script >
< script src = "js/hndse.min.js" > < / script >
< script src = "js/app.min.js" > < / script >
<!-- Init script -->
< script >
$(function() {
// Create the app
var app = new Hnd.App();
// Update translations
hnd_ut(app);
// Instanciate imageMapResizer
imageMapResize();
// Custom JS
// Boot the app
app.Boot();
});
< / script >
< / body >
2012-03-23 20:30:31 +00:00
< / html >