def Exch(): global Asm if MissingOperand(): return reg1 = assem.GetWord().upper() if not assem.MoreParameters(): errors.DoError('missoper', False) return reg2 = assem.GetWord().upper() if (reg1 == 'DE') and (reg2 == 'HL'): index = 0 elif (reg1 == 'AF') and (reg2 == "AF'"): index = 1 elif (reg1 == '(SP)') and (reg2 == 'HL'): index = 2 elif (reg1 == '(SP)') and (reg2 == 'IX'): index = 3 elif (reg1 == '(SP)') and (reg2 == 'IY'): index = 4 else: errors.DoError('badoper', False) return Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][index]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index] NoMore()
def Pairs(): """ Handle paired operand instructions. """ global Asm if MissingOperand(): return reg1 = assem.GetWord().upper() if not assem.MoreParameters(): errors.DoError('missoper', False) return if assem.NowChar() == ' ': errors.DoError('missoper', False) return if assem.NowChar() in '#/=\\': reg2 = '#' else: reg2 = assem.GetWord().upper() operand = reg1 + ',' + reg2 operands = dec.Asm.Instructions[dec.Asm.Mnemonic][1] opcodes = dec.Asm.Instructions[dec.Asm.Mnemonic][2] times = dec.Asm.Instructions[dec.Asm.Mnemonic][3] if operand in operands: index = 0 for t in operands: if t == operand: break index = index + 1 target.CodeByte(opcodes[index]) dec.Asm.Timing = times[index] if reg2 == '#': prefix = assem.NowChar(True) value = assem.EvalExpr() if prefix == '#': target.CodeByte(value[0]) elif prefix == '/': target.CodeByte(value[0] >> 8) elif prefix == '=': target.CodeByte(value[0] >> 16) else: target.CodeByte(value[0] >> 24) else: errors.DoError('badoper', False) NoMore()
def MovBit(): """ See if first or second operand is a C. If it is it is a bit MOV. If it is not return False and parse normal MOV. """ global Asm # Save the begin pointer in case're on a dead track pntr = dec.Asm.Parse_Pointer par1 = assem.GetWord().upper() if not assem.MoreParameters(): # We need 2 paarameters errors.DoError('missoper', False) return if par1 == 'C': # First parameter is a C bitreg = GetBit() target.CodeByte(0xA2) target.CodeByte(bitreg) dec.Asm.Timing = '1' NoMore() return True par2 = assem.GetWord().upper() if par2 == 'C': # Second parameter is a C endpntr = dec.Asm.Parse_Pointer dec.Asm.Parse_Pointer = pntr bitreg = GetBit() dec.Asm.Parse_Pointer = endpntr target.CodeByte(0x92) target.CodeByte(bitreg) dec.Asm.Timing = '2' NoMore() return True # Nope, it's not MOV C, restore pointer and try again dec.Asm.Parse_Pointer = pntr return False
def Exchange(): """ Handle EXG and TFR directives. Both directives take 2 operands of either 8-bit size or 16-bit size. Sizes of the registers may not be mixed. """ global Asm if MissingOperand(): return reg1 = assem.GetWord().upper() if not assem.MoreParameters(): errors.DoError('missoper', False) return reg2 = assem.GetWord().upper() words = { 'A:B': 0, 'D': 0, 'X': 1, 'Y': 2, 'US': 3, 'U': 3, 'SP': 4, 'S': 4, 'PC': 5 } bytes = {'A': 8, 'B': 9, 'CC': 10, 'CCR': 10, 'DP': 11, 'DPR': 11} if reg1 in words: if reg2 in words: target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1]) target.CodeByte((words[reg1] << 4) + words[reg2]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] else: errors.DoError('badoper', False) elif reg1 in bytes: if reg2 in bytes: target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1]) target.CodeByte((bytes[reg1] << 4) + bytes[reg2]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] else: errors.DoError('badoper', False) else: errors.DoError('badoper', False) NoMore()
def Pointer(): """ Pointer pair instructions PntrPair """ global Asm MissingOperand() parsepointer = dec.Asm.Parse_Pointer pointer = -1 pntr = assem.GetWord().upper() if len(pntr) == 2 and pntr[1] == "P": # It might as well be a poiner pair if pntr[0] >= '0' and pntr[0] <= '7': # It sure is pointer = int(pntr[0]) * 2 if pointer == -1: # It wasn't a pointer, so it must be an expression now dec.Asm.Parse_Pointer = parsepointer pointer = assem.EvalExpr()[0] if dec.Asm.Pass == 2: # Range check only in pass 2 if pointer < 0 or pointer > 15 or pointer % 2 == 1: # Range error errors.DoError('range', False) target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + pointer) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] NoMore()
def GetPtr(): """ A pointer parameter is expected. Legal options are P0, PC, P1, P2 or P3 They translate to 0..3, where P0 and PC are equal and generate 0 """ global Asm pointer = dec.Asm.Parse_Pointer param = assem.GetWord().upper() if param == '': errors.DoError('missoper', False) return 0 if len(param) == 2 and param[0] == 'P': param = param[1] if param.isdigit(): ptr = int(param) if ptr > 3: errors.DoError('badoper', False) else: if param == 'C': ptr = 0 else: errors.DoError('badoper', False) ptr = 0 else: errors.DoError('badoper', False) ptr = 0 return ptr % 4
def DirFA(): """ Set the device's family. If this is not used in a program a warning is given and the assembler defaults to the XMega family, which can do everything. As of version 3.02.00 of this cross overlay an extra family tree has been added to reflect the families found on Wikipedia. This allows for a much finer distinction between the capabilities of the processors. The old family tree still exists though for backward compatibility. - Boundary Sync. """ global Asm target.BoundarySync() families = [ 'TINY', 'AVR', 'MEGA', 'XMEGA', 'REDUCED', 'MINIMAL', 'CLASSIC8K' ] families += ['CLASSIC128K', 'ENHANCED8K', 'ENHANCED128K', 'ENHANCED4M'] if dec.Asm.Parse_Pointer == 0: # No parameter given errors.DoError('missoper', False) return family = assem.GetWord().upper() if family not in families: errors.DoError('badoper', False) return dec.Asm.AVR_Family = families.index(family) + 1 NoMore()
def DirDE(): """ Assign a name to a register. - Boundary Sync will be automatic because of the label in the label field """ global Asm if dec.Asm.Parse_Pointer == 0: # No parameter given errors.DoError('missoper', False) dec.Asm.New_Label = '' return register = -1 reg = assem.GetWord().upper() if (len(reg) == 2 or len(reg) == 3) and reg[0] == 'R': # Can it be a register name? Must be 2 or 3 chars long and start with R reg = reg[1:] if reg.isdigit: # The register number must be numeric of course if len(reg) == 1 or reg[0] != '0': # It is numeric, without a leading 0 register = int(reg) if register < 0 or register > 31: # It is not a legal register errors.DoError('badoper', False) dec.Asm.New_Label = '' else: # It is a legal register, set it's value dec.Asm.BOL_Address = register dec.Asm.List_Address = register dec.Asm.Mnemonic = '.SE' # Handle rest like .SE
def DefineMacro(): global Asm labelfield = '' mnemonic = '' if dec.Asm.Parse_Line.isspace() or dec.Asm.Parse_Line[0] in dec.COMMENT1: # This line contains nothing or comment, don't parse it pass else: if dec.Asm.Parse_Line[0] != ' ': # Get label name, but don't bother about syntax labelfield = assem.GetWord() mnemonic = assem.GetMnemonic() if mnemonic != '' and mnemonic[0] == '.': # See if any of the reserved mnemonics is given mnemonic = mnemonic[1:3] if mnemonic in ('MA', 'IN', 'CH', 'BI', 'CO', 'EC'): errors.DoError('illdir', False) return # Don't add this line to the macro definition if mnemonic == 'EM': # End the macro definition if labelfield != '': # The .EM line doesn't allow a label declaration errors.DoError('illdec', False) dec.Asm.New_Label = '' dec.Asm.Macro_Def = '' return # Don't add this line to the definition! if dec.Asm.Pass == 1: # Only add to the definition during pass 1 dec.Asm.Macro[dec.Asm.Macro_Def].append(dec.Asm.Parse_Line)
def Singles(): """ Handle single operand instructions. """ global Asm if MissingOperand(): return regname = assem.GetWord().upper() registers = dec.Asm.Instructions[dec.Asm.Mnemonic][1] opcodes = dec.Asm.Instructions[dec.Asm.Mnemonic][2] times = dec.Asm.Instructions[dec.Asm.Mnemonic][3] if regname in registers: index = 0 for t in registers: if t == regname: break index = index + 1 target.CodeByte(opcodes[index]) dec.Asm.Timing = times[index] else: errors.DoError('badoper', False) NoMore()
def Returns(): global Asm conditions = { 'NZ': 0, 'Z': 1, 'NC': 2, 'C': 3, 'PO': 4, 'PE': 5, 'P': 6, 'M': 7 } if dec.Asm.Optional: # Parameter was following within 10 spaces condition = assem.GetWord().upper() if condition in conditions: cond = conditions[condition] << 3 index = 1 else: cond = 0 index = 0 else: cond = 0 index = 0 Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][index] + cond) dec.Asm.Instructions[dec.Asm.Mnemonic][2][index] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index] NoMore()
def Stack(): global Asm if MissingOperand(): return operand = assem.GetWord().upper() if operand == 'A': index = 0 elif operand == 'X': index = 1 elif operand == 'Y': index = 2 elif operand == 'CC': index = 3 else: errors.DoError('badoper', False) return opcode = (dec.Asm.Instructions[dec.Asm.Mnemonic][1][index]) if opcode > 255: target.CodeWord(opcode) else: target.CodeByte(opcode) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index] NoMore()
def Stack(): global Asm if MissingOperand(): return pair = assem.GetWord().upper() if pair in ('BC', 'DE', 'HL', 'AF'): if pair == 'DE': offset = 16 elif pair == 'HL': offset = 32 elif pair == 'AF': offset = 48 else: offset = 0 Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + offset) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] elif pair in ('IX', 'IY'): if pair == 'IX': prefix = 0xDD else: prefix = 0xFD Code(prefix) Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + 32) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1] else: errors.DoError('badoper', False) NoMore()
def GetReg(): global Asm pointer = dec.Asm.Parse_Pointer register = assem.GetWord().upper() if register == 'A': return (1, 0xFF) elif register == "X": return (2, 0x80) elif register == "Y": return (3, 0x81) elif register == "V": return (4, 0x82) elif register == "W": return (5, 0x83) elif register == "(X)": return (6, 0) elif register == "(Y)": return (7, 0) else: dec.Asm.Parse_Pointer = pointer value = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (value > 255 or value < 0): errors.DoError('range', False) value = value & 255 return (0, value)
def GetDest(): """ Get the destination for register file instructions. It can either accept W or F or nothing. Or it can accept any expression as long as it returns 0 or 1 """ global Asm dest = 0x80 if assem.MoreParameters(): # Direction is specified temp = dec.Asm.Parse_Pointer direction = assem.GetWord().upper() if direction == "W": # Direction towards W register dest = 0 elif direction == "F": # Direction towards File register dest = 0x80 else: # Neither W nor F. Must be an expression now dec.Asm.Parse_Pointer = temp dest = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (dest < 0 or dest > 1): # That's a range error! errors.DoError('range', False) dest = (dest & 1) * 0x80 return dest
def Multiply(): global Asm if MissingOperand(): return operand1 = assem.GetWord().upper() if operand1 not in 'XY': errors.DoError('badoper', False) return if not assem.MoreParameters(): errors.DoError('missoper', False) return if assem.NowChar(True).upper() != 'A': errors.DoError('badoper', False) return if operand1 == 'X': target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] else: target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1] NoMore()
def Math(): global Asm if MissingOperand(): return opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] if assem.GetWord().upper() != 'A': errors.DoError('badoper', False) return if not assem.MoreParameters(): errors.DoError('missoper', False) return value = GetReg() for i in range(0, len(opcode[value[0]]), 2): byte = opcode[value[0]][i:i + 2] if byte == 'XX': target.CodeByte(value[1]) else: target.CodeByte(int(byte, 16)) dec.Asm.Timing = timing[value[0]] NoMore()
def Branch(): global Asm if MissingOperand(): return conditions = {'C': 1, 'NC': 2, 'Z': 3, 'NZ': 4} pointer = dec.Asm.Parse_Pointer condition = assem.GetWord().upper() if dec.Asm.Mnemonic == 'JR' and condition in conditions and\ assem.NowChar(True) == ',': index = conditions[condition] else: dec.Asm.Parse_Pointer = pointer index = 0 value = assem.EvalExpr() offset = value[0] - dec.Asm.BOL_Address - 2 if dec.Asm.Pass == 2 and (offset < -128 or offset > 127): errors.DoError('range', False) Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][index]) target.CodeByte(offset) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][index] NoMore()
def GetDest(filereg): """ Get the destination for register file instructions. It can either accept W or F or nothing. Or it can accept any expression as long as it returns 0 or 1. Only when a destination is given the optional access bank selector can also be given. If not, the assembler will pick the proper access bank mode for you. """ global Asm dest = 0x200 if assem.MoreParameters(): # Direction is specified temp = dec.Asm.Parse_Pointer direction = assem.GetWord().upper() if direction == "W": # Direction towards W register dest = 0 elif direction == "F": # Direction towards File register dest = 0x200 else: # Neither W nor F. Must be an expression now dec.Asm.Parse_Pointer = temp dest = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (dest < 0 or dest > 1): # That's a range error! errors.DoError('range', False) dest = (dest & 1) * 0x200 if assem.MoreParameters(): # Good, the access bank selector is given. That's easy accessbank = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (accessbank < 0 or accessbank > 1): # Oops, this is not good errors.DoError('range', False) else: # Now we have to decide accessbank = 0 if filereg >= dec.Asm.AccessBank18 and filereg <\ (dec.Asm.AccessBank18 + 0xF00): # Outside of access bank range. Use BSR mode instead accessbank = 1 else: # Direction was not specified, so access bank select is also automatic accessbank = 0 if filereg >= dec.Asm.AccessBank18 and filereg <\ (dec.Asm.AccessBank18 + 0xF00): # Outside of access bank range. Use BSR mode instead accessbank = 1 dest += (accessbank & 1) << 8 return dest
def Jumps(): global Asm if MissingOperand(): return if assem.NowChar() == '@': # It is an indirect jump reg1 = GetReg() if reg1[0] == '@rr' or reg1[0] == '@R': target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1]) target.CodeByte(reg1[1]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1] if reg1[1] & 1 != 0: errors.DoError('range', False) else: errors.DoError('badoper', False) else: # It's not an indirect jump if dec.Asm.Mnemonic == 'CALL': # It's a CALL instruction opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] else: # It's JP instruction conditions = {'F': 0x00, 'C': 0x70, 'NC': 0xF0, 'Z': 0x60, 'NZ': 0xE0, 'PL': 0xD0, 'MI': 0x50, 'OV': 0x40, 'NOV': 0xC0, 'EQ': 0x60, 'NE': 0xE0, 'GE': 0x90, 'LT': 0x10, 'GT': 0xA0, 'LE': 0x20, 'UGE': 0xF0, 'ULT': 0x70, 'UGT': 0xB0, 'ULE': 0x30} pointer = dec.Asm.Parse_Pointer cond = assem.GetWord().upper() if cond in conditions and assem.NowChar() == ',': # A legal condition code was given opcode = conditions[cond] + 13 dec.Asm.Timing = '10+' if not assem.MoreParameters(): errors.DoError('missoper', False) return else: # No condition was given dec.Asm.Parse_Pointer = pointer dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0] dest = assem.EvalExpr() target.CodeByte(opcode) target.CodeWord(dest[0]) if dec.Asm.Pass == 2 and (dest[0] >> 16) != 0: errors.DoError('range', False) NoMore()
def PointerData(): """ Pointer pair with data instructions pointer,data """ global Asm MissingOperand() parsepointer = dec.Asm.Parse_Pointer pointer = -1 pntr = assem.GetWord().upper() if len(pntr) == 2 and pntr[1] == "P": # It might as well be a poiner pair if pntr[0] >= '0' and pntr[0] <= '7': # It sure is pointer = int(pntr[0]) * 2 if pointer == -1: # It wasn't a pointer, so it must be an expression now dec.Asm.Parse_Pointer = parsepointer pointer = assem.EvalExpr()[0] if not assem.MoreParameters(): errors.DoError('missoper', False) return prefix = '#' if assem.NowChar() in '#/=\\': prefix = assem.NowChar(True) value = assem.EvalExpr() if prefix == '#': val = value[0] & 255 elif prefix == '/': val = (value[0] >> 8) & 255 elif prefix == '=': val = (value[0] >> 16) & 255 else: val = (value[0] >> 24) & 255 if dec.Asm.Pass == 2: # Range check only in pass 2 if pointer < 0 or pointer > 15 or pointer % 2 == 1: # Range error errors.DoError('range', False) target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + pointer) target.CodeByte(val) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] NoMore()
def Djnz(): """ Handle DJNZ. DJNZ has two opcodes in the instruction table. The first one is for DJNZ Rx,dest. The second entry is for DJNZ @Rn,dest. If indirect mode doesn't exist the opcode for it should be 00. """ global Asm if MissingOperand(): return registers = ('R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', '@R0', '@R1') regname = assem.GetWord().upper() if regname in registers: index = 0 for t in registers: if t == regname: break index = index + 1 if index < 8: # direct addressing mode opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0] + index else: # indirect addressing mode opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][1] if opcode == 0: errors.DoError('badoper', False) return opcode = opcode + (index & 1) else: errors.DoError('badoper', False) return if not assem.MoreParameters(): errors.DoError('missoper', False) return value = assem.EvalExpr() if dec.Asm.Pass == 2: temp = (dec.Asm.BOL_Address + 1) >> 8 dest = value[0] >> 8 if temp != dest: # Destination is not in the same memory page errors.DoError('range', False) target.CodeByte(opcode) target.CodeByte(value[0]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] NoMore()
def Jumps(): global Asm if MissingOperand(): return conditions = { 'NZ': 0, 'Z': 1, 'NC': 2, 'C': 3, 'PO': 4, 'PE': 5, 'P': 6, 'M': 7 } pointer = dec.Asm.Parse_Pointer condition = assem.GetWord().upper() if condition in conditions and assem.NowChar(True) == ',': # Conditional jump or call if assem.NowChar() == " ": # Allow a space to follow a comma assem.IncParsePointer() value = assem.EvalExpr() Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1] + (conditions[condition] << 3)) target.CodeWord(value[0]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1] if dec.Asm.Pass == 2 and ((value[0] >> 16) != 0): errors.DoErrors('range', False) elif condition == '(HL)': # (HL) Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][2]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][2] elif condition == '(IX)': # (IX) Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][3]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][3] elif condition == '(IY)': # (IY) Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][4]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][3] else: # Non conditional dec.Asm.Parse_Pointer = pointer value = assem.EvalExpr() Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1][0]) target.CodeWord(value[0]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] NoMore()
def GetBit(): """ Legal bit addresses are: Direct addresses from 020H.0 to 02FH.7 SFR addresses which can be devided by 8, followed by .0 to .7 If the address is not followed by .0 to .7 it is handled as a normal address, in which case its value should be below 256. """ global Asm pntr = dec.Asm.Parse_Pointer par1 = assem.GetWord().upper() regbit = 0 if len(par1) > 2 and par1[-2] == '.' and par1[-1] in '01234567': # operand.bit notation. Hide bit number temporarily bitno = int(par1[-1]) parseline = dec.Asm.Parse_Line dec.Asm.Parse_Line = parseline[:dec.Asm.Parse_Pointer - 2] + ' ' dec.Asm.Parse_Pointer = pntr value = assem.EvalExpr() dec.Asm.Parse_Line = parseline dec.Asm.Parse_Pointer = dec.Asm.Parse_Pointer + 2 if dec.Asm.Pass == 2: # Only check rage during pass 2 if value[0] in range(0x20, 0x30): # In RAM area regbit = ((value[0] & 15) << 3) + bitno elif value[0] in range(0x80, 0xFF, 8): # In SFR area regbit = value[0] + bitno else: # Not in legal area errors.DoError('range', False) else: # No operand.bit notation, evaluate normally dec.Asm.Parse_Pointer = pntr value = assem.EvalExpr() regbit = value[0] if dec.Asm.Pass == 2 and (value[0] >> 8) != 0: # Value not between 0 to 255 errors.DoError('range', False) return regbit
def GetPtr(): """ A pointer parameter is expected. Legal options are P0, PC, P1, P2 or P3 They translate to 0..3, where P0 and PC are equal and generate 0. For compatibility digits 0, 1, 2 and 3 are also accepted. """ global Asm pointer = dec.Asm.Parse_Pointer param = assem.GetWord().upper() if param == '': # Empty parameter not allowed errors.DoError('missoper', False) return 0 if len(param) == 2 and param[0] == 'P': # Strip leading P if parameter length = 2 param = param[1] if param == 'C': # Translate PC parameter to 0 param = '0' if len(param) == 1: # Parameter length may only be 1 now if param.isdigit(): # The parameter must be digit from 0 to 3 now ptr = int(param) if ptr > 3: errors.DoError('badoper', False) else: # Parameter was not a digit errors.DoError('badoper', False) ptr = 0 else: # Parameter length was not 1 errors.DoError('badoper', False) ptr = 0 return ptr % 4
def BitInst(): """ Handle CLR, CPL and SETB instructions. """ global Asm if MissingOperand(): # Oops, no operands return pntr = dec.Asm.Parse_Pointer par1 = assem.GetWord().upper() if par1 == 'A': # A parameter opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1][0] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][0] if opcode == 0: # Opcode doesn't exist errors.DoError('badoper', False) else: # Opcode exists target.CodeByte(opcode) elif par1 == 'C': # C parameter target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][1]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][1] else: # It's a bit adddress dec.Asm.Parse_Pointer = pntr par1 = GetBit() target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1][2]) target.CodeByte(par1) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2][2] NoMore()
def Output(): global Asm if MissingOperand(): return operand = assem.GetWord().upper() outputlist = { 'ADR': 0x51, 'STATUS': 0x53, 'DATA': 0x55, 'WRITE': 0x57, 'COM1': 0x59, 'COM2': 0x5B, 'COM3': 0x5D, 'COM4': 0x5F, 'BEEP': 0x69, 'CLICK': 0x6B, 'DECK1': 0x6D, 'DECK2': 0x6F, 'RBK': 0x71, 'WBK': 0x73, 'BSP': 0x77, 'SF': 0x79, 'SB': 0x7B, 'REWIND': 0x7D, 'TSTOP': 0x7F } if operand in outputlist: target.CodeByte(outputlist[operand]) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] else: errors.DoError('badoper', False) NoMore()
def TableRW(): """ The parameter can be the following: * 00 *+ 01 *- 10 +* 11 """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] first = assem.NowChar() option = assem.GetWord("*+-", "*+-", " ") if option == "*": # Just the pointer CodeWord(opcode) elif option == "*+": # Post increment CodeWord(opcode + 1) elif option == "*-": # Post decerement CodeWord(opcode + 2) elif option == "+*": # Pre increment CodeWord(opcode + 3) else: # It's an error, but which one? if first == " ": # Missing operand errors.DoError("missoper", False) else: # Bad operand errors.DoError("badoper", False)
def Mult(): global Asm if MissingOperand(): return pair = assem.GetWord().upper() if pair in ('BC', 'DE', 'HL', 'SP'): if pair == 'DE': offset = 16 elif pair == 'HL': offset = 32 elif pair == 'SP': offset = 48 else: offset = 0 Code(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + offset) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] else: errors.DoError('badoper', False) NoMore()
def GetOperand(): """ Get an operand. This can get complicated. Operand can be: Index = 0: # Index = 1: SHORT Index = 2: LONG Index = 3: (X) Index = 4: (SHORT,X) Index = 5: (LONG,X) Index = 6: (Y) Index = 7: (SHORT,Y) Index = 8: (LONG,Y) Index = 9: [SHORT] Index = 10: [LONG.W] Index = 10: {LONG} Index = 11: ([SHORT],X) Index = 12: ([LONG.W],X) Index = 12: ({LONG},X) Index = 13: ([SHORT],Y) Index = 14: ([LONG.W],Y) Index = 14: ({LONG},Y) Index = 15: A Index = 16: X Index = 17: Y Index = 18: S """ global Asm pntr = dec.Asm.Parse_Pointer operand = assem.GetWord().upper() if operand == 'A': return (15, 0) if operand == 'X': return (16, 0) if operand == 'Y': return (17, 0) if operand == 'S': return (18, 0) if operand == '(X)': return (3, 0) if operand == '(Y)': return (6, 0) dec.Asm.Parse_Pointer = pntr # ---------- if operand[0] in '#/=\\': # Immediate value mode = assem.NowChar(True) value = assem.EvalExpr() if mode == '#': return (0, value[0]) if mode == '/': return (0, value[0] >> 8) if mode == '=': return (0, value[0] >> 16) return (0, value[0] >> 24) # ---------- if operand[0:2] == '([': # Some form of Indexed Indirect mode assem.IncParsePointer() assem.IncParsePointer() pntr = dec.Asm.Parse_Pointer line = dec.Asm.Parse_Line operand = assem.GetWord('', '', ']').upper() endpnt = dec.Asm.Parse_Pointer dec.Asm.Parse_Pointer = pntr short = True if operand[-2:] == '.W': short = False dec.Asm.Parse_Line = line[:endpnt - 2] + ' ' value = assem.EvalExpr() dec.Asm.Parse_Line = line dec.Asm.Parse_Pointer = endpnt if assem.NowChar(True) != ']': errors.DoError('badoper', False) if not assem.MoreParameters(): errors.DoError('missoper', False) nowchar = assem.NowChar(True).upper() if nowchar == 'X': xymode = 11 elif nowchar == 'Y': xymode = 13 else: xymode = 11 errors.DoError('badoper', False) if assem.NowChar(True) != ')': errors.DoError('badoper', False) if dec.Asm.Pass == 2 and (value[0] >> 8 != 0): errors.DoError('range', False) if short: return (xymode + 0, value[0]) else: return (xymode + 1, value[0]) # ---------- if operand[0:2] == '({': # Indexed Indirect long mode assem.IncParsePointer() assem.IncParsePointer() value = assem.EvalExpr() if assem.NowChar(True) != '}': errors.DoError('badoper', False) if not assem.MoreParameters(): errors.DoError('missoper', False) nowchar = assem.NowChar(True).upper() if nowchar == 'X': xymode = 12 elif nowchar == 'Y': xymode = 14 else: xymode = 12 errors.DoError('badoper', False) if assem.NowChar(True) != ')': errors.DoError('badoper', False) if dec.Asm.Pass == 2 and (value[0] >> 8 != 0): errors.DoError('range', False) return (xymode, value[0]) # ---------- if operand[0] == '(': # Some form of indexed mode. # It can be short or long, followed by ,X) or ,Y) assem.IncParsePointer() prefix = '' if operand[0] in '<>': # It's forced long or short prefix = assem.NowChar(True) value = assem.EvalExpr() if prefix == '<': short = True if dec.Asm.Pass == 2 and (value[0] >> 8) != 0: errors.DoError('range', False) elif prefix == '>' or value[1]: short = False else: short = False if (value[0] >> 8) == 0: short = True if not assem.MoreParameters(): errors.DoError('missoper', False) nowchar = assem.NowChar(True).upper() if nowchar == 'X': xymode = 4 elif nowchar == 'Y': xymode = 7 else: xymode = 4 errors.DoError('badoper', False) if assem.NowChar(True) != ')': errors.DoError('badoper', False) if short: return (xymode + 0, value[0]) else: return (xymode + 1, value[0]) # ---------- if operand[0] == '[': # Some form of indirect mode, could be [short] or [long.w] assem.IncParsePointer() pntr = dec.Asm.Parse_Pointer line = dec.Asm.Parse_Line operand = assem.GetWord('', '', ']').upper() endpnt = dec.Asm.Parse_Pointer dec.Asm.Parse_Pointer = pntr short = True if operand[-2:] == '.W': short = False dec.Asm.Parse_Line = line[:endpnt - 2] + ' ' value = assem.EvalExpr() dec.Asm.Parse_Line = line dec.Asm.Parse_Pointer = endpnt if assem.NowChar(True) != ']': errors.DoError('badoper', False) if dec.Asm.Pass == 2 and (value[0] >> 8 != 0): errors.DoError('range', False) if short: return (9, value[0]) else: return (10, value[0]) # ---------- if operand[0] == '{': # Indirect LONG mode assem.IncParsePointer() value = assem.EvalExpr() if assem.NowChar(True) != '}': errors.DoError('badoper', False) if dec.Asm.Pass == 2 and (value[0] >> 8 != 0): errors.DoError('range', False) return (10, value[0]) # ---------- # Here only short or long mode option left. # Must decide whether to use short or long, depending on address size prefix = '' if operand[0] in '<>': # It's forced long or short prefix = assem.NowChar(True) value = assem.EvalExpr() if prefix == '<': short = True if dec.Asm.Pass == 2 and (value[0] >> 8) != 0: errors.DoError('range', False) elif prefix == '>' or value[1]: short = False else: short = False if (value[0] >> 8) == 0: short = True if short: return (1, value[0]) else: return (2, value[0])