#!/usr/bin/env python

ABS_X = "ABS_X"
ABS_Y = "ABS_Y"
ABS = "ABS"
IND_X = "IND_X"
IND_Y = "IND_Y"
Z = "Z"
Z_X = "Z_X"
Z_Y = "Z_Y"
A = None
HASH = "#"
rel = "rel"
IND = "IND" # jump indirect

# None none
manual_opcode_adr = {
	0: None, 
	1: IND_X, 
	2: -1, 
	4: Z, 
	5: Z, 
	6: Z, 
	8: None, 
	9: HASH, 
	10: A, 
	12: ABS, 
	13: ABS, 
	14: ABS, 
	16: rel, 
	17: IND_Y, 
	20: Z_X, 
	21: Z_X, 
	22: Z_X, 
	24: None, 
	25: ABS_Y, 
	26: A, 
	28: ABS_X, 
	29: ABS_X, 
	30: ABS_X, 
	32: ABS,
	33: IND_X, 
	36: Z, 
	37: Z, 
	38: Z, 
	41: HASH, 
	42: A, 
	44: ABS, 
	45: ABS, 
	46: ABS, 
	48: rel, 
	49: IND_Y, 
	52: Z_X, 
	53: Z_X, 
	54: Z_X, 
	56: None, 
	57: ABS_Y, 
	58: A, 
	60: ABS_X, 
	61: ABS_X, 
	62: ABS_X, 
	64: None, 
	65: IND_X, 
	68: Z, 
	69: Z, 
	70: Z,
	72: None, 
	73: HASH, 
	74: A, 
	76: ABS, 
	77: ABS, 
	78: ABS, 
	80: rel, 
	81: IND_Y, 
	84: Z_X, 
	85: Z_X, 
	86: Z_X, 
	88: None,
	89: ABS_Y, 
	90: A, 
	92: ABS_X, 
	93: ABS_X, 
	94: ABS_X, 
	96: None, 
	97: IND_X, 
	100: Z, 
	101: Z,
	102: Z, 
	104: None, 
	105: HASH, 
	106: A, 
	108: IND, 
	109: ABS, 
	110: ABS, 
	112: rel, 
	113: IND_Y, 
	116: Z_X, 
	117: Z_X, 
	118: Z_X, 
	120: None, 
	121: ABS_Y, 
	122: A, 
	124: ABS_X, 
	125: ABS_X, 
	126: ABS_X, 
	128: HASH, 
	129: IND_X, 
	130: HASH, 
	132: Z, 
	133: Z, 
	134: Z, 
	136: None, 
	137: HASH,
	138: None, 
	140: ABS,
	141: ABS, 
	142: ABS, 
	144: rel, 
	145: IND_Y, 
	148: Z_X, 
	149: Z_X, 
	150: Z_Y, 
	152: None, 
	153: ABS_Y, 
	154: None,
	155: ABS_Y, 
	157: ABS_X, 
	160: HASH, 
	161: IND_X, 
	162: HASH, 
	164: Z, 
	165: Z, 
	166: Z, 
	168: None, 
	169: HASH, 
	170: None, 
	172: ABS, 
	173: ABS, 
	174: ABS, 
	176: rel, 
	177: IND_Y, 
	180: Z_X, 
	181: Z_X,
	182: Z_Y, 
	184: None, 
	185: ABS_Y, 
	186: None, 
	188: ABS_X, 
	189: ABS_X, 
	190: ABS_Y, 
	192: HASH, 
	193: IND_X,
	194: HASH, 
	196: Z, 
	197: Z, 
	198: Z, 
	200: None, 
	201: HASH, 
	202: None, 
	204: ABS, 
	205: ABS, 
	206: ABS, 
	208: rel, 
	209: IND_Y, 
	212: Z_X, 
	213: Z_X, 
	214: Z_X, 
	217: ABS_Y, 
	216: None, 
	218: A, 
	220: ABS_X,
	221: ABS_X, 
	222: ABS_X, 
	224: HASH, 
	225: IND_X, 
	226: HASH, 
	228: Z, 
	229: Z, 
	230: Z, 
	232: None, 
	233: HASH, 
	234: A, 
	236: ABS, 
	237: ABS, 
	238: ABS, 
	240: rel, 
	241: IND_Y, 
	244: Z_X,
	245: Z_X, 
	246: Z_X, 
	248: None, 
	249: ABS_Y, 
	250: A, 
	252: ABS_X, 
	253: ABS_X, 
	254: ABS_X,
	0x28: None}

AD = [('ADC_addressing_modes', {97: IND_X, 113: IND_Y, 101: Z, 121: ABS_Y, 105: HASH, 125: ABS_X, 109: ABS, 117: Z_X}),
('AND_addressing_modes', {33: IND_X, 61: ABS_X, 37: Z, 57: ABS_Y, 41: HASH, 49: IND_Y, 45: ABS, 53: Z_X}),
('ASL_addressing_modes', {30: ABS_X, 10: A, 14: ABS, 22: Z_X, 6: Z}),
('BIT_addressing_modes', {44: ABS, 36: Z}),
('CMP_addressing_modes', {193: IND_X, 221: ABS_X, 197: Z, 217: ABS_Y, 201: HASH, 209: IND_Y, 205: ABS, 213: Z_X}),
('CPX_addressing_modes', {224: HASH, 236: ABS, 228: Z}),
('CPY_addressing_modes', {192: HASH, 204: ABS, 196: Z}),
('DEC_addressing_modes', {206: ABS, 222: ABS_X, 214: Z_X, 198: Z}),
('EOR_addressing_modes', {65: IND_X, 69: Z, 81: IND_Y, 89: ABS_Y, 73: HASH, 77: ABS, 93: ABS_X, 85: Z_X}),
('INC_addressing_modes', {238: ABS, 246: Z_X, 230: Z, 254: ABS_X}),
('LDA_addressing_modes', {189: ABS_X, 177: IND_Y, 165: Z, 185: ABS_Y, 169: HASH, 173: ABS, 161: IND_X, 181: Z_X}),
('LDX_addressing_modes', {162: HASH, 190: ABS_Y, 182: Z_Y, 166: Z, 174: ABS}),
('LDY_addressing_modes', {160: HASH, 180: Z_X, 172: ABS, 164: Z, 188: ABS_X}),
('LSR_addressing_modes', {74: A, 94: ABS_X, 78: ABS, 86: Z_X, 70: Z}),
('NOP_addressing_modes', {128: Z, 130: Z, 4: Z, 137: Z, 12: ABS, 20: Z_X, 26: A, 155: ABS_Y, 28: ABS_X, 218: A, 92: ABS_X, 52: Z_X, 244: Z_X, 58: A, 60: ABS_X, 194: Z, 68: Z, 84: Z_X, 90: A, 220: ABS_X, 250: A, 226: Z, 100: Z, 252: ABS_X, 234: A, 116: Z_X, 212: Z_X, 122: A, 124: ABS_X}),
('ORA_addressing_modes', {1: IND_X, 17: IND_Y, 5: Z, 25: ABS_Y, 9: HASH, 29: ABS_X, 13: ABS, 21: Z_X}),
('ROL_addressing_modes', {62: ABS_X, 42: A, 46: ABS, 54: Z_X, 38: Z}),
('ROR_addressing_modes', {126: ABS_X, 106: A, 110: ABS, 118: Z_X, 102: Z}),
('SBC_addressing_modes', {225: IND_X, 253: ABS_X, 229: Z, 249: ABS_Y, 233: HASH, 241: IND_Y, 237: ABS, 245: Z_X}),
('STA_addressing_modes', {129: IND_X, 133: Z, 141: ABS, 145: IND_Y, 149: Z_X, 153: ABS_Y, 157: ABS_X}),
('STX_addressing_modes', {150: Z_Y, 134: Z, 142: ABS}),
('STY_addressing_modes', {148: Z_X, 140: ABS, 132: Z}),
]
opcodes_by_adr = {}
for n, items in AD:
	for opcode, adr in items.items():
		if adr not in opcodes_by_adr:
			opcodes_by_adr[adr] = []
		opcodes_by_adr[adr].append(opcode)
opcodes_by_adr[None] = []
for opcode, adr in manual_opcode_adr.items():
	if adr is None:
		opcodes_by_adr[None].append(opcode)
for adr, opcodes in opcodes_by_adr.items():
	print adr, ":", " ".join([hex(opcode) for opcode in opcodes])
# ends in c,d,e: ABS(major digit is even),ABS_X(major digit is odd)
# ends in 4,5,6: Z_X,Z
# ends in a: A
# ends in 9: HASH(even),ABS_Y(odd)

unsupported_opcodes = [0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x92, 0xB2, 0xD2, 0xF2,
	# SLO
	3, 7, 0xF, 
	0x13, 0x17, 0x1B, 0x1F,
	# ANC
	0xB, 0x2B,
	# RLA
	0x23, 0x27, 0x2F,
	0x33, 0x37, 0x3B, 0x3F,
	# SRE
	0x43, 0x47, 0x4F, 
	0x53, 0x57, 0x5B, 0x5F,
	# ALR
	0x4B, 
	# RRA
	0x63, 0x67, 0x6F,
	0x73, 0x77, 0x7B, 0x7F,
	# ARR
	0x6B, 
	# SAX
	0x83, 0x87, 0x8F,
	0x97, 0x9F, 
	# XAA
	0x8B,
	# AHX
	0x93, 0x9F,
	# SHY
	0x9C,
	# SHX
	0x9E,
	# LAX
	0xA3, 0xA7, 0xAB, 0xAF, #!!! LDA LDX LDY LAX
	0xB3, 0xB7, 0xBF,
	# LAS
	0xBB,
	# DCP
	0xC3, 0xC7, 0xCF,
	0xD3, 0xD7, 0xDB, 0xDF,
	# AXS
	0xCB,
	# ISC
	0xE3, 0xE7, 0xEF,
	0xF3, 0xF7, 0xFB, 0xFF,
	# SBC
	0xEB,
]
# None end with 8,a,0
for opcode in range(256):
	v = None
	if opcode in unsupported_opcodes:
		continue
	manual_adr = manual_opcode_adr[opcode]
	X_section = opcode & 0x10
	end = opcode & 0xF
	adr = None
	if opcode in [0, 0x40, 0x60]:
		adr = None
	elif opcode in [0xB6, 0x96]:
		adr = "Z_Y"
	elif opcode in [0xBE, 0x9B]:
		adr = "ABS_Y"
	elif opcode in [0x80, 0x82, 0x89, 0xA0, 0xC0, 0xC2, 0xE0, 0xE2, 0xA2]:
		adr = "#"
	elif opcode == 0x6C:
		adr = "IND" # has its very own addressing mode
	elif end == 1:
		if X_section: # ?????
			adr = "IND_Y"
		else:
			adr = "IND_X"
	elif end == 0:
		if X_section:
			adr = "rel"
		else:
			adr = "ABS"
	elif end in [4,5,6]:
		# Z or Z_X
		if X_section:
			adr = "Z_X"
		else:
			adr = "Z"
	elif end in [0xc, 0xd, 0xe]:
		# ABS or ABS_X
		if X_section:
			adr = "ABS_X"
		else:
			adr = "ABS"
	elif end == 9:
		# # or ABS_Y
		if X_section:
			adr = "ABS_Y"
		else:
			adr = "#"
	if adr != manual_adr:
		print("adr %s manual_adr %s for opcode %X" % (adr, manual_adr, opcode))
if False:
	minor_section = opcode & 0xC
	major_section = opcode & 0x10
	if minor_section == 0xC:
		# either ABS or ABS_X
		if major_section:
			v = ABS_X
		else:
			v = ABS
	elif minor_section == 0x1:
		# either Z_X or Z
		v = Z_X # FIXME or Z
	elif minor_section == 0x8: # A transfer instructions
		# A|HASH(even)|ABS_Y(odd)
		if major_section:
			v = ABS_Y # FIXME or A
		else:
			v = HASH
	if v != manual_adr:
		print "%s is not %s for operator %X" % (v, manual_adr, opcode)
