summaryrefslogtreecommitdiff
path: root/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py
diff options
context:
space:
mode:
Diffstat (limited to 'source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py')
-rw-r--r--source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py526
1 files changed, 526 insertions, 0 deletions
diff --git a/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py
new file mode 100644
index 0000000..15c2791
--- /dev/null
+++ b/source/notes/pic-mcu/pickit2/pk2cmd-stuff/pic18.py
@@ -0,0 +1,526 @@
+def render(instr):
+ if 'ops' in instr:
+ optexts = []
+ for op in instr['ops']:
+ if isinstance(op, dict) and 'type' in op:
+ optext = op['text'] if 'text' in op else hex(op['value'])
+ optexts.append(optext)
+ else:
+ optexts.append(str(op))
+ return "{} {}".format(instr['mnemonic'], ', '.join(optexts))
+ else:
+ return instr['mnemonic']
+
+def sext(number, bit):
+ mask = 1 << bit
+ if number & mask > 0:
+ return - ((~number & (mask - 1)) + 1)
+ else:
+ return number
+
+NAMES = {
+ 0xF60: '_ZERO_',
+ 0xF61: '_ZERO_',
+ 0xF62: 'SPPDATA',
+ 0xF63: 'SPPCFG',
+ 0xF64: 'SPPEPS',
+ 0xF65: 'SPPCON',
+ 0xF66: 'UFRML',
+ 0xF67: 'UFRMH',
+ 0xF68: 'UIR',
+ 0xF69: 'UIE',
+ 0xF6A: 'UEIR',
+ 0xF6B: 'UEIE',
+ 0xF6C: 'USTAT',
+ 0xF6D: 'UCON',
+ 0xF6E: 'UADDR',
+ 0xF6F: 'UCFG',
+ 0xF70: 'UEP0',
+ 0xF71: 'UEP1',
+ 0xF72: 'UEP2',
+ 0xF73: 'UEP3',
+ 0xF74: 'UEP4',
+ 0xF75: 'UEP5',
+ 0xF76: 'UEP6',
+ 0xF77: 'UEP7',
+ 0xF78: 'UEP8',
+ 0xF79: 'UEP9',
+ 0xF7A: 'UEP10',
+ 0xF7B: 'UEP11',
+ 0xF7C: 'UEP12',
+ 0xF7D: 'UEP13',
+ 0xF7E: 'UEP14',
+ 0xF7F: 'UEP15',
+ 0xF80: 'PORTA',
+ 0xF81: 'PORTB',
+ 0xF82: 'PORTC',
+ 0xF83: 'PORTD',
+ 0xF84: 'PORTE',
+ 0xF85: '_ZERO_',
+ 0xF86: '_ZERO_',
+ 0xF87: '_ZERO_',
+ 0xF88: '_ZERO_',
+ 0xF89: 'LATA',
+ 0xF8A: 'LATB',
+ 0xF8B: 'LATC',
+ 0xF8C: 'LATD',
+ 0xF8D: 'LATE',
+ 0xF8E: '_ZERO_',
+ 0xF8F: '_ZERO_',
+ 0xF90: '_ZERO_',
+ 0xF91: '_ZERO_',
+ 0xF92: 'TRISA',
+ 0xF93: 'TRISB',
+ 0xF94: 'TRISC',
+ 0xF95: 'TRISD',
+ 0xF96: 'TRISE',
+ 0xF97: '_ZERO_',
+ 0xF98: '_ZERO_',
+ 0xF99: '_ZERO_',
+ 0xF9A: '_ZERO_',
+ 0xF9B: 'OSCTUNE',
+ 0xF9C: '_ZERO_',
+ 0xF9D: 'PIE1',
+ 0xF9E: 'PIR1',
+ 0xF9F: 'IPR1',
+ 0xFA0: 'PIE2',
+ 0xFA1: 'PIR2',
+ 0xFA2: 'IPR2',
+ 0xFA3: '_ZERO_',
+ 0xFA4: '_ZERO_',
+ 0xFA5: '_ZERO_',
+ 0xFA6: 'EECON1',
+ 0xFA7: 'EECON2',
+ 0xFA8: 'EEDATA',
+ 0xFA9: 'EEADR',
+ 0xFAA: '_ZERO_',
+ 0xFAB: 'RCSTA',
+ 0xFAC: 'TXSTA',
+ 0xFAD: 'TXREG',
+ 0xFAE: 'RCREG',
+ 0xFAF: 'SPBRG',
+ 0xFB0: 'SPBRGH',
+ 0xFB1: 'T3CON',
+ 0xFB2: 'TMR3L',
+ 0xFB3: 'TMR3H',
+ 0xFB4: 'CMCON',
+ 0xFB5: 'CVRCON',
+ 0xFB6: 'ECCP1AS',
+ 0xFB7: 'ECCP1DEL',
+ 0xFB8: 'BAUDCON',
+ 0xFB9: '_ZERO_',
+ 0xFBA: 'CCP2CON',
+ 0xFBB: 'CCPR2L',
+ 0xFBC: 'CCPR2H',
+ 0xFBD: 'CCP1CON',
+ 0xFBE: 'CCPR1L',
+ 0xFBF: 'CCPR1H',
+ 0xFC0: 'ADCON2',
+ 0xFC1: 'ADCON1',
+ 0xFC2: 'ADCON0',
+ 0xFC3: 'ADRESL',
+ 0xFC4: 'ADRESH',
+ 0xFC5: 'SSPCON2',
+ 0xFC6: 'SSPCON1',
+ 0xFC7: 'SSPSTAT',
+ 0xFC8: 'SSPADD',
+ 0xFC9: 'SSPBUF',
+ 0xFCA: 'T2CON',
+ 0xFCB: 'PR2',
+ 0xFCC: 'TMR2',
+ 0xFCD: 'T1CON',
+ 0xFCE: 'TMR1L',
+ 0xFCF: 'TMR1H',
+ 0xFD0: 'RCON',
+ 0xFD1: 'WDTCON',
+ 0xFD2: 'HLVDCON',
+ 0xFD3: 'OSCCON',
+ 0xFD4: '_ZERO_',
+ 0xFD5: 'T0CON',
+ 0xFD6: 'TMR0L',
+ 0xFD7: 'TMR0H',
+ 0xFD8: 'STATUS',
+ 0xFD9: 'FSR2L',
+ 0xFDA: 'FSR2H',
+ 0xFDB: 'PLUSW2',
+ 0xFDC: 'PREINC2',
+ 0xFDD: 'POSTDEC2',
+ 0xFDE: 'POSTINC2',
+ 0xFDF: 'INDF2',
+ 0xFE0: 'BSR',
+ 0xFE1: 'FSR1L',
+ 0xFE2: 'FSR1H',
+ 0xFE3: 'PLUSW1',
+ 0xFE4: 'PREINC1',
+ 0xFE5: 'POSTDEC1',
+ 0xFE6: 'POSTINC1',
+ 0xFE7: 'INDF1',
+ 0xFE8: 'WREG',
+ 0xFE9: 'FSR0L',
+ 0xFEA: 'FSR0H',
+ 0xFEB: 'PLUSW0',
+ 0xFEC: 'PREINC0',
+ 0xFED: 'POSTDEC0',
+ 0xFEE: 'POSTINC0',
+ 0xFEF: 'INDF0',
+ 0xFF0: 'INTCON3',
+ 0xFF1: 'INTCON2',
+ 0xFF2: 'INTCON',
+ 0xFF3: 'PRODL',
+ 0xFF4: 'PRODH',
+ 0xFF5: 'TABLAT',
+ 0xFF6: 'TBLPTRL',
+ 0xFF7: 'TBLPTRH',
+ 0xFF8: 'TBLPTRU',
+ 0xFF9: 'PCL',
+ 0xFFA: 'PCLATH',
+ 0xFFB: 'PCLATU',
+ 0xFFC: 'STKPTR',
+ 0xFFD: 'TOSL',
+ 0xFFE: 'TOSH',
+ 0xFFF: 'TOSU'
+}
+
+def reg_name(number):
+ if number in NAMES:
+ return NAMES[number]
+ else:
+ return None
+
+def disassemble(blob, offset):
+ instr = {}
+ instr['length'] = 1
+ instrbytes = blob[offset:offset + 2]
+ instrbytes.reverse()
+# instrbytes.reverse()
+# print("Decoding {:02x}{:02x}...".format(instrbytes[0], instrbytes[1]))
+
+ if instrbytes[0] == 0x00:
+ # there's a few instructions here...
+ if instrbytes[1] == 0xff:
+ instr['mnemonic'] = 'reset'
+ else:
+ mnemonicmap = [
+ 'nop',
+ 'BAD',
+ 'BAD',
+ 'sleep',
+ 'clrwdt',
+ 'push',
+ 'pop',
+ 'daw',
+ 'tblrd*',
+ 'tblrd*+',
+ 'tblrd*-',
+ 'tblrd+*',
+ 'tblwr*',
+ 'tblwr*+',
+ 'tblwr*-',
+ 'tblwr+*',
+ 'retfie',
+ 'retfie fast',
+ 'return',
+ 'return fast',
+ 'callw*']
+
+ if instrbytes[1] > len(mnemonicmap):
+ instr['mnemonic'] = 'BAD'
+ else:
+ instr['mnemonic'] = mnemonicmap[instrbytes[1]]
+ elif instrbytes[0] == 0x01:
+ if instrbytes[1] > 0xf:
+ instr['mnemonic'] = 'BAD'
+ else:
+ instr['mnemonic'] = 'movlb'
+ instr['ops'] = ["#" + str(instrbytes[1])]
+ elif instrbytes[0] == 0x02 or instrbytes[0] == 0x03:
+ instr['mnemonic'] = 'mulwf'
+ instr['ops'] = ['TODO']
+ elif instrbytes[0] >= 0x04 and instrbytes[0] < 0x08:
+ instr['mnemonic'] = 'decf'
+ d = (instrbytes[0] >> 1) & 1
+ a = instrbytes[0] & 1
+ f = instrbytes[1]
+ if a == 0:
+ # "Access Bank"
+ f_physical = f if f < 0x60 else 0xf00 + f
+ source = {
+ 'type': 'register',
+ 'value': f_physical
+ }
+ else:
+ source = {
+ 'type': 'banked-register',
+ 'value': f
+ }
+
+ if d == 0:
+ dest = { 'type': 'register',
+ 'value': 'W' }
+ else:
+ dest = source
+
+ if a == 0:
+ instr['ops'] = [ source, dest ]
+ else:
+ instr['ops'] = [ source, dest, 'banked' ]
+
+ elif instrbytes[0] >= 0x08 and instrbytes[0] < 0x10:
+ code = instrbytes[0] & 0x7
+
+ instr['mnemonic'] = [
+ 'sublw',
+ 'iorlw',
+ 'xorlw',
+ 'andlw',
+ 'retlw',
+ 'mullw',
+ 'movlw',
+ 'addlw'
+ ][code]
+ instr['ops'] = ['#' + hex(instrbytes[1])]
+ elif instrbytes[0] >= 0x10 and instrbytes[0] < 0x20:
+ code = (instrbytes[0] >> 2) & 0x3
+ instr['mnemonic'] = [
+ 'iorwf',
+ 'andwf',
+ 'xorwf',
+ 'comf'
+ ][code]
+ d = (instrbytes[0] >> 1) & 1
+ a = instrbytes[0] & 1
+ f = instrbytes[1]
+
+ if a == 0:
+ # "Access Bank"
+ f_physical = f if f < 0x60 else 0xf00 + f
+ source = {
+ 'type': 'register',
+ 'value': f_physical
+ }
+ else:
+ source = {
+ 'type': 'banked-register',
+ 'value': f
+ }
+
+ if d == 0:
+ dest = { 'type': 'register',
+ 'value': 'W' }
+ else:
+ dest = source
+
+ if a == 0:
+ instr['ops'] = [ source, dest ]
+ else:
+ instr['ops'] = [ source, dest, 'banked' ]
+
+ elif instrbytes[0] >= 0x20 and instrbytes[0] < 0x60:
+ mnemonicSel = instrbytes[0] >> 2
+ instr['mnemonic'] = [
+ 'mulwf (TODO)', #000000
+ 'decf', #000001
+ 'BAD', 'BAD', #00001X
+ 'iorwf', #000100
+ 'andwf', #000101
+ 'xorwf', #000110
+ 'comf', #000111
+ 'addwfc', #001000
+ 'addwf', #001001
+ 'incf', #001010
+ 'decfsz', #001011
+ 'rrcf', #001100
+ 'rlcf', #001101
+ 'swapf', #001110
+ 'incfsz', #001111
+ 'rrncf', #010000
+ 'rlncf', #010001
+ 'infsnz', #010010
+ 'dcfsnz', #010011
+ 'movf', #010100
+ 'subwfb', #010101
+ 'subwfb', #000000
+ 'subwf' #000000
+ ][mnemonicSel]
+ d = (instrbytes[0] >> 1) & 1
+ a = instrbytes[0] & 1
+ f = instrbytes[1]
+
+ if a == 0:
+ # "Access Bank"
+ f_physical = f if f < 0x60 else 0xf00 + f
+ source = {
+ 'type': 'register',
+ 'value': f_physical
+ }
+ else:
+ source = {
+ 'type': 'banked-register',
+ 'value': f
+ }
+
+ if d == 0:
+ dest = { 'type': 'register',
+ 'value': 'W' }
+ else:
+ dest = source
+
+ if a == 0:
+ instr['ops'] = [ source, dest ]
+ else:
+ instr['ops'] = [ source, dest, 'banked' ]
+
+ elif instrbytes[0] >= 0x60 and instrbytes[0] < 0x70:
+ mnemonicSel = (instrbytes[0] >> 1) & 0x7
+ instr['mnemonic'] = [
+ 'cpfslt',
+ 'cpfseq',
+ 'cpfsgt',
+ 'tstfsz',
+ 'setf',
+ 'clrf',
+ 'negf',
+ 'movwf'
+ ][mnemonicSel]
+ a = instrbytes[0] & 1
+ f = instrbytes[1]
+ if a == 0:
+ # "Access Bank"
+ f_physical = f if f < 0x60 else 0xf00 + f
+ instr['ops'] = [
+ { 'type': 'register',
+ 'value': f_physical }
+ ]
+ else:
+ instr['ops'] = [
+ { 'type': 'banked-register',
+ 'value': f },
+ "banked"
+ ]
+ elif instrbytes[0] >= 0x70 and instrbytes[0] < 0xc0:
+ mnemonicSel = instrbytes[0] >> 4
+ instr['mnemonic'] = [
+ 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD', 'BAD',
+ 'btg',
+ 'bsf',
+ 'bcf',
+ 'btfss',
+ 'btfsc'
+ ][mnemonicSel]
+ bit = (instrbytes[0] >> 1) & 0x7
+ a = instrbytes[0] & 1
+ f = instrbytes[1]
+ if a == 0:
+ # "Access Bank"
+ f_physical = f if f < 0x60 else 0xf00 + f
+ instr['ops'] = [
+ { 'type': 'register',
+ 'value': f_physical },
+ bit
+ ]
+ else:
+ instr['ops'] = [
+ { 'type': 'banked-register',
+ 'value': f },
+ bit,
+ "banked"
+ ]
+ elif instrbytes[0] >= 0xc0 and instrbytes[0] < 0xd0:
+ instr['mnemonic'] = 'movff'
+ instr['length'] = 2
+ fs = ((instrbytes[0] & 0xf) << 8) | instrbytes[1]
+ followingbytes = blob[offset + 2:offset + 4]
+ followingbytes.reverse()
+ if followingbytes[0] < 0xf0:
+ instr['mnemonic'] = 'movff (BAD)'
+ else:
+ fd = ((followingbytes[0] & 0xf) << 8) | followingbytes[1]
+ instr['ops'] = [
+ { 'type': 'register',
+ 'value': fs },
+ { 'type': 'register',
+ 'value': fd }
+ ]
+ elif instrbytes[0] >= 0xd0 and instrbytes[0] < 0xd8:
+ instr['mnemonic'] = 'bra'
+ n = ((instrbytes[0] & 0x7) << 8) | instrbytes[1]
+ n = sext(n, 10)
+ instr['ops'] = [{
+ 'type': 'relpostdest',
+ 'value': n << 1
+ }]
+ elif instrbytes[0] >= 0xd8 and instrbytes[0] < 0xe0:
+ instr['mnemonic'] = 'rcall'
+ n = ((instrbytes[0] & 0x7) << 8) | instrbytes[1]
+ instr['ops'] = [{
+ 'type': 'relpostdest',
+ 'value': n << 1
+ }]
+ elif instrbytes[0] >= 0xe0 and instrbytes[0] <= 0xe8:
+ code = instrbytes[0] & 0x7
+ instr['mnemonic'] = [
+ 'bz',
+ 'bnz',
+ 'bc',
+ 'bnc',
+ 'bov',
+ 'bnov',
+ 'bn',
+ 'bnn'
+ ][code]
+ n = instrbytes[1]
+ n = sext(n, 7)
+ instr['ops'] = [{
+ 'type': 'relpostdest',
+ 'value': n << 1
+ }]
+ elif instrbytes[0] >= 0xf0 and instrbytes[0] <= 0xff:
+ instr['mnemonic'] = 'BAD (misdecode)'
+ elif instrbytes[0] == 0xea:
+ instr['mnemonic'] = 'push'
+ instr['ops'] = [instrbytes[1]]
+ elif instrbytes[0] == 0xec or instrbytes[0] == 0xed:
+ instr['mnemonic'] = 'call'
+ s = instrbytes[0] & 1
+ instr['length'] = 2
+ lowbits = instrbytes[1]
+ followingbytes = blob[offset + 2:offset + 4]
+ followingbytes.reverse()
+ if followingbytes[0] < 0xf0:
+ instr['mnemonic'] = 'CALL (BAD)'
+ else:
+ k = (((followingbytes[0] & 0x0f) << 16) | (followingbytes[1] << 8) | lowbits)
+ instr['ops'] = [{
+ 'type': 'absolutedest',
+ 'value': k << 1
+ }, str(s)]
+ elif instrbytes[0] == 0xee:
+ instr['mnemonic'] = 'lfsr'
+ instr['length'] = 2
+ f = (instrbytes[1] >> 4) & 3
+ followingbytes = blob[offset + 2:offset + 4]
+ followingbytes.reverse()
+ if followingbytes[0] < 0xf0:
+ instr['mnemonic'] = 'lsfr (BAD)'
+ else:
+ k = ((instrbytes[1] & 0xf) << 8) | followingbytes[1]
+ instr['ops'] = [str(f), hex(k)]
+ elif instrbytes[0] == 0xef:
+ instr['mnemonic'] = 'goto'
+ instr['length'] = 2
+ lowbits = instrbytes[1]
+ followingbytes = blob[offset + 2:offset + 4]
+ followingbytes.reverse()
+ if followingbytes[0] < 0xf0:
+ instr['mnemonic'] = 'GOTO (BAD)'
+ else:
+ k = ((followingbytes[0] & 0x0f) << 16) | (followingbytes[1] << 8) | lowbits
+ instr['ops'] = [{
+ 'type': 'absolutedest',
+ 'value': k << 1
+ }]
+
+ else:
+ instr['mnemonic'] = 'TODO'
+
+ return (offset + instr['length'] * 2, instr)