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 Bits(): """ Handle Bit instructions Both bit set/clr as well as branch bit set/clr instructions are handled by this routine. """ global Asm if MissingOperand(): return bitno = assem.EvalExpr()[0] opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] + ((bitno & 7)) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] if not assem.MoreParameters(): # We expected more parameters errors.DoError('missoper', False) return param = dec.Asm.Parse_Line[dec.Asm.Parse_Pointer:dec.Asm.Parse_Pointer+2]\ .upper() if param in ('A,', 'X,', 'Y,', 'A ', 'X ', 'Y '): assem.NowChar(True) if param[0] == 'A': mem = 255 elif param[0] == 'X': mem = 128 else: mem = 129 else: mem = assem.EvalExpr()[0] if dec.Asm.Mnemonic[1] == 'R': # It's a branch instruction if not assem.MoreParameters(): # We expected more parameters errors.DoError('missoper', False) return dest = assem.EvalExpr()[0] offset = dest - dec.Asm.BOL_Address - 3 target.CodeByte(opcode) target.CodeByte(mem) target.CodeByte(offset) if dec.Asm.Pass == 2 and (offset < -128 or offset > +127): errors.DoError('range', False) else: # It wasn't a branch instruction target.CodeByte(opcode) target.CodeByte(mem) if dec.Asm.Pass == 2: if (bitno < 0 or bitno > 7) or (mem < 0 or mem > 255): errors.DoError('range', False) NoMore()
def BranchBit(): """ Handle the bit test branch instructions. """ global Asm if MissingOperand(): # We need operands return dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] par1 = GetBit() if not assem.MoreParameters(): # Oops only one operand given errors.DoError('missoper', False) return value = assem.EvalExpr() offset = value[0] - dec.Asm.BOL_Address - 3 if dec.Asm.Pass == 2 and (offset < -128 or offset > 127): # Out of range errors.DoError('range', False) target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1]) target.CodeByte(par1) target.CodeByte(offset) NoMore()
def Conditional(): """ Conditional instructions reg,dest con,dest """ global Asm if MissingOperand(): return val = assem.EvalExpr()[0] if not assem.MoreParameters(): errors.DoError('missoper', False) return dest = assem.EvalExpr()[0] if dec.Asm.Pass == 2: if (val < 0 or val > 15): # Range error errors.DoError('range', False) # !!!! isz on last 2 locations of page causes jump to next page. Strange but # true according to page 3-42 target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + (val & 15)) target.CodeByte(dest) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] NoMore()
def NoMore(): """ No more operands shoudl follow. Raise a warning if more parameters follow. """ if assem.MoreParameters(): errors.DoWarning('extrign', False)
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 BitInst(): """ Bit instructions. These require 2 operands. The first is the register number from 0 to 31. The second is the bit number from 0 to 7. Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles """ global Asm reg = GetReg() << 4 if not assem.MoreParameters(): # Only the register number is given, the bit number is missing errors.DoError('missoper', False) # Write dummy word target.CodeWord(0) return bitno = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (bitno < 0 or bitno > 7): # Report range error if bit number not between 0 and 7 errors.DoError('range', False) bitno = 0 target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + reg + bitno) NoMore()
def XchdInst(): """ Handle the XCHD instruction. """ global Asm if MissingOperand(): # No parameters return dec.Asm.Timing = '1' if assem.NowChar(True).upper() != 'A': # First paramter must be an A errors.DoError('badoper', False) return if not assem.MoreParameters(): # Only one parameter given errors.DoError('missoper', False) return par2 = GetReg() if par2[1] != 3: # Second parameter may only be @Ri errors.DoError('badoper', False) return target.CodeByte(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + par2[0]) NoMore()
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 FileFile(): """ MOVFF instruction. Moves a file register to a file register. Both can be addressed directly with 12-bits. Source or destination can be the W register, if the WREG SFR is used. The PCL, TOSU, TOSH and TOSL can't be used as destination. A range error is reported if you do use these. No other range checking is done though. """ global Asm source = assem.EvalExpr()[0] & 0xFFF if not assem.MoreParameters(): # Missing 2nd operand errors.DoError('missoper', False) dest = 0 else: dest = assem.EvalExpr()[0] & 0xFFF CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][1] + source) CodeWord(0xF000 + dest) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] if dec.Asm.Pass == 2 and dest in [0xFF9, 0xFFD, 0xFFE, 0xFFF]: # PCL, TOSL, TOSH and TOSU can't be used as destination errors.DoError('range', False) NoMore()
def FileBit(): """ File register and bit operations. Only the bit address is being range checked. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] filereg = assem.EvalExpr()[0] if assem.MoreParameters(): # Oh, good, something else is following bit = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (bit < 0 or bit > 7): # Illegal bit number errors.DoError('range', False) bit = bit & 0x07 else: # Oops, missing operand errors.DoError('missoper', False) bit = 0 CodeWord(opcode + (filereg & 0x7F) + (bit << 7)) NoMore()
def Immediate(): """ Immediate operand instructions. Instructions optionally accept the traditional # / = and \ prefixes. Only the RETLW instruction will accept multiple operatnds, which are stored sequentially in program memory. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] if opcode == 0x0C00: # Operand field may be empty for RETLW instruction if dec.Asm.Parse_Pointer == 0 or dec.Asm.Optional is False: # No parameter is following CodeWord(opcode) return while True: prefix = '#' if assem.NowChar() in '#/=\\': # A prefix is given, let's get it prefix = assem.NowChar(True) value = assem.EvalExpr()[0] if dec.Asm.Mnemonic == "BANKSEL": # BANKSEL is the same as MOVLB with modified operand value = (value // 256) & 0x0F if not dec.Flags.ErrorInLine: # No error in this line, let's continue if prefix == '#': # Keep lower byte value = value & 0xFF elif prefix == '/': # Keep 2nd lower byte value = (value >> 8) & 0xFF elif prefix == '=': # Keep 2nd upper byte value = (value >> 16) & 0xFF else: # Keep upper byte value = (value >> 24) & 0xFF if opcode == 0x0100: # MOVLB range is limited to 4 bits value = value & 0x0F CodeWord(opcode + value) if not assem.MoreParameters(): # No more parameters break if opcode != 0x0C00: # Only the RETLW instruction allows multiple literal bytes errors.DoWarning('extrign', False)
def FileOnly(): """ These instructions only require a file register as operand. No range checking is done. When access bank selector is missing the assembler will determine the access bank or BSR mode for you. The access bank selector may only be either 0 or 1. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] value = assem.EvalExpr()[0] 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 value >= dec.Asm.AccessBank18 and value <\ (dec.Asm.AccessBank18 + 0xF00): # Outside of access bank range. Use BSR mode instead accessbank = 1 accessbank = (accessbank & 1) << 8 CodeWord(opcode + (value & 0x0FF) + accessbank) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] NoMore()
def Lfsr(): """ File one of the 4 File select register pointers with a 12 bit file register address. File register number is not range checked. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] pointer = assem.EvalExpr()[0] if not assem.MoreParameters(): # Missing operand errors.DoError('missoper', False) register = 0 else: # Get the operand register = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (pointer < 0 or pointer > 3): # Range error errors.DoError('range', False) pointer = pointer & 3 CodeWord(opcode + (pointer << 4) + ((register >> 8) & 0xF)) CodeWord(0xF000 + (register & 0xFF)) NoMore()
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 BitInst(): global Asm if MissingOperand(): return opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] bitno = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (bitno > 7 or bitno < 0): assem.DoError('range', False) bitno = bitno & 7 if not assem.MoreParameters(): errors.DoError('missoper', False) return datareg = GetReg() if datareg[0] > 5: assem.DoError('badoper', False) datareg = datareg[1] target.CodeByte(opcode + BitSwap(bitno)) target.CodeByte(datareg) dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] 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 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 NoMore(): """ No more parameters are expected. Raise a warning if more paramters are found anyway. """ if assem.MoreParameters(): errors.DoWarning('extrign', False)
def FileBit(): """ File register and bit operations. The file address is being range checked in order to determine the Access Bank selection. The bit range is also checked. The access bank selection parameter is optional. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] filereg = assem.EvalExpr()[0] bitno = 0 accessbank = 0 if not assem.MoreParameters(): # Missing operand errors.DoError('missoper', False) else: # Get the operand bitno = assem.EvalExpr()[0] 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 if filereg >= dec.Asm.AccessBank18 and filereg <\ (dec.Asm.AccessBank18 + 0xF00): # Outside of access bank range. Use BSR mode instead accessbank = 1 accessbank = (accessbank & 1) << 8 if dec.Asm.Pass == 2 and (bitno < 0 or bitno > 7): # Range error in bit number errors.DoError('range', False) CodeWord(opcode + (filereg & 0xFF) + (bitno << 9) + accessbank) NoMore()
def NoMore(): """ A useful function which tests if no more parameters are given when we don't expect any more at the end of the operand parsing. """ if assem.MoreParameters(): errors.DoWarning('extrign', False)
def NoMore(): """ This must be the end of the line. Raise an error if it's not. Or a warning if more parameters follow. """ if assem.MoreParameters(): errors.DoWarning('extrign', False)
def Load(): global Asm if MissingOperand(): return reg1 = GetReg() if dec.Flags.ErrorInLine: # An error was found in parameter 1, no need to continue return if not assem.MoreParameters(): errors.DoError('missoper', False) return reg2 = GetReg() firstpar = 'LD.' + reg1[0] if firstpar in dec.Asm.Instructions: secpar = dec.Asm.Instructions[firstpar][0] opcode = dec.Asm.Instructions[firstpar][1] timing = dec.Asm.Instructions[firstpar][2] extra = dec.Asm.Instructions[firstpar][3] index = 0 for t in secpar: if t == reg2[0]: # Found 2nd parameter, now let's save it to the target file opc = opcode[index] Code(opc) dec.Asm.Timing = timing[index] if extra[index] == 1: # save one extra byte from operand 2 target.CodeByte(reg2[1]) elif extra[index] == 2: # save two extra bytes from operand 2 target.CodeWord(reg2[1]) elif extra[index] == 3: # save one extra byte from operand 1 target.CodeByte(reg1[1]) elif extra[index] == 4: # save one extra byte from operand 1 and one from operand 2 target.CodeByte(reg1[1]) target.CodeByte(reg2[1]) elif extra[index] == 5: # save two extra bytes from operand 1 target.CodeWord(reg1[1]) NoMore() return index = index + 1 # This type of parameter was not allowed as second parameter errors.DoError('badoper', False) else: # This type of parameter was not allowed as first parameter errors.DoError('badoper', False)
def InOut(): """ These instructions require two operands. A register from 0 to 31 and an I/O address from 0 to 63. The IN and OUT instructions have their operand order swapped. Dictionary: function, Xmega+Mega+AVR+TINY, newflags, opcode, cycles """ global Asm if dec.Asm.Mnemonic == 'IN': # Get register operand first, then I/O location reg = GetReg() << 4 if not assem.MoreParameters(): # Oops only register is given errors.DoError('missoper', False) target.CodeWord(0) # Write dummy word return value = assem.EvalExpr()[0] else: # Get I/O location first, then register value = assem.EvalExpr()[0] if not assem.MoreParameters(): # Oops, only I/O location given errors.DoError('missoper', False) target.CodeWord(0) # Write dummy word return reg = GetReg() << 4 if dec.Asm.Pass == 2 and (value < 0 or value > 63): # Check I/O address range in pass 2 only errors.DoError('range', False) value = 0 ioreg = (value & 15) + ((value & 48) << 5) target.CodeWord(dec.Asm.Instructions[dec.Asm.Mnemonic][3] + reg + ioreg) NoMore()
def LDIndexed(): """ LD indexed takes 2 operands. A register number and an index register, which may include a pre-decrement or a post-increment. The Y and Z index registers may also have an offset from the register's base value. The range of this offset is from 0 to 63. Reduced instructionset only has LD Rd,Z. All others are off limits. This is not correctly implemented in the legacy family and cannot be fixed! Dictionary: function, Xmega+Mega+AVR+TINY, newflags, 1 or 0, cycles """ global Asm reg = GetReg() << 4 if not assem.MoreParameters(): # Only the register was given. The index register is missing errors.DoError('missoper', False) target.CodeWord(0) # Write dummy word return value = GetIndex() if value[1] == 'X': # Get the opcode for LD Rn,X if dec.Asm.AVR_Family == 6: # Illegal index register for this minimal core errors.DoError('badoper', False) opcode = 0x900C elif value[1] == 'Y': # Get the opcode for LD(D) Rn,Y and add offset to it if dec.Asm.AVR_Family == 6: # Illegal index register for this minimal core errors.DoError('badoper', False) opcode = 0x8008 + value[2] if value[0] != 0 and len(dec.Asm.Mnemonic) == 2: # Indicated pre-decrement or post-increment opcode opcode = opcode + 0x1000 else: # Get the opcode for LD(D) Rn,Z and add offset to it opcode = 0x8000 + value[2] if value[0] != 0 and len(dec.Asm.Mnemonic) == 2: # Indicate pre-decrement or post-increment opcode if dec.Asm.AVR_Family == 6: # pre-decrement and post-increment not implemented errors.DoError('badoper', False) opcode = opcode + 0x1000 if len(dec.Asm.Mnemonic) == 2: # It's LD, not LDD, add the pre-decrement or post-increment flag to it opcode = opcode + value[0] target.CodeWord(opcode + reg) NoMore()
def Immediate(): """ Immediate operand instructions. Instructions optionally accept the traditional # / = and \ prefixes. Only GOTO and CALL don't, they are only tolerant to the # prefix Only the RETLW instruction will accept multiple operatnds, which are stored sequentially in program memory. """ global Asm opcode = dec.Asm.Instructions[dec.Asm.Mnemonic][1] dec.Asm.Timing = dec.Asm.Instructions[dec.Asm.Mnemonic][2] if opcode == 0x3400: # Operand field may be empty for RETLW instruction if dec.Asm.Parse_Pointer == 0 or dec.Asm.Optional is False: # No parameter is following CodeWord(opcode) return while True: prefix = '#' if assem.NowChar() in '#/=\\': # A prefix is given, let's get it prefix = assem.NowChar(True) value = assem.EvalExpr() if not dec.Flags.ErrorInLine: # No error in this line, let's continue if opcode == 0x2000 or opcode == 0x2800: # Allow 11 bits of operand for GOTO CodeWord(opcode + (value[0] & 0x7FF)) if prefix != '#': # Only the default prefix is allowed errors.DoError('badoper', False) elif prefix == '#': # Save opcode and lower byte CodeWord(opcode + (value[0] & 0xFF)) elif prefix == '/': # Save opcode and 2nd lower byte CodeWord(opcode + ((value[0] >> 8) & 0xFF)) elif prefix == '=': # Save opcode and 2nd upper byte CodeWord(opcode + ((value[0] >> 16) & 0xFF)) else: # Save opcode and upper byte CodeWord(opcode + ((value[0] >> 24) & 0xFF)) if not assem.MoreParameters(): # No more parameters break if opcode != 0x3400: # Only the RETLW instruction allows multiple literal bytes errors.DoWarning('extrign', False)
def STIndexed(): """ ST indexed takes 2 operands. An index register, which may include a pre-decrement or a post-increment, and a register. The Y and Z index registers may also have an offset from the register's base value. The range of this offset is from 0 to 63. Reduced instructionset only has ST Z,Rd. All others are off limits. This is not correctly implemented in the legacy family and cannot be fixed! Dictionary: function, Xmega+Mega+AVR+TINY, newflags, 1 or 0, cycles """ global Asm value = GetIndex() if value[1] == 'X': # Get opcode for ST X,Rn if dec.Asm.AVR_Family == 6: # Illegal index register for this minimal core errors.DoError('badoper', False) opcode = 0x920C elif value[1] == 'Y': # Get opcode for ST(D) Y,Rn and add offset to it if dec.Asm.AVR_Family == 6: # Illegal index register for this minimal core errors.DoError('badoper', False) opcode = 0x8208 + value[2] if value[0] != 0 and len(dec.Asm.Mnemonic) == 2: # Indicated pre-decrement or post-increment opcode opcode = opcode + 0x1000 else: # Get opcode for ST(D) Z,Rn and add offset to it opcode = 0x8200 + value[2] if value[0] != 0 and len(dec.Asm.Mnemonic) == 2: # Indicated pre-decrement or post-increment opcode if dec.Asm.AVR_Family == 6: # pre-decrement and post-increment not implemented errors.DoError('badoper', False) opcode = opcode + 0x1000 if len(dec.Asm.Mnemonic) == 2: # It's ST, not STD, add the pre-decrement or post-increment flag to it opcode = opcode + value[0] if not assem.MoreParameters(): errors.DoError('missoper', False) target.CodeWord(0) # Write dummy word return reg = GetReg() << 4 target.CodeWord(opcode + reg) NoMore()
def MovXInst(): """ MOVX A,@DPTR MOV A,@Ri MOV @DPTR,A MOV @Ri,A """ global Asm if MissingOperand(): # We need some operands return par1 = GetReg() if not assem.MoreParameters(): # Only one operand given errors.DoError('missoper', False) return par2 = GetReg() dec.Asm.Timing = '2' if par1[1] == 1: # Can be either A,@DPTR or A,@Ri if par2[1] == 7: # It's A,@DPTR for sure target.CodeByte(0xE0) elif par2[1] == 3: # It's A,@Ri target.CodeByte(0xE2 + par2[0]) else: # None of the above errors.DoError('badoper', False) return elif par1[1] == 7: # It's @DPTR,A mode if par2[1] != 1: # Second parameter is not A errors.DoError('badoper', False) return target.CodeByte(0xF0) elif par1[1] == 3: # It's @Ri,A mode if par2[1] != 1: # Second parameter is not A errors.DoError('badoper', False) return target.CodeByte(0xF2 + par1[0]) else: # 1st parameter is wrong errors.DoError('badoper', False) return NoMore()
def CpInst(): global Asm if MissingOperand(): return operand1 = GetOperand() if not assem.MoreParameters(): errors.DoError('missoper', False) return operand2 = GetOperand() if operand1[0] == 15: # CP A,something opcode = (0x00A1, 0x00B1, 0x00C1, 0x00F1, 0x00E1, 0x00D1, 0x90F1, 0x90E1, 0x90D1, 0x92B1, 0x92C1, 0x92E1, 0x92D1, 0x91E1, 0x91D1) timing = ('2', '3', '4', '3', '4', '5', '4', '5', '6', '5', '6', '6', '7', '6', '7') elif operand1[0] == 16: # CP X,something opcode = (0x00A3, 0x00B3, 0x00C3, 0x00F3, 0x00E3, 0x00D3, 0x0000, 0x0000, 0x0000, 0x92B3, 0x92C3, 0x92E3, 0x92D3, 0x0000, 0x0000) timing = ('2', '3', '4', '3', '4', '5', '0', '0', '0', '5', '6', '6', '7', '0', '0') elif operand1[0] == 17: # CP Y,something opcode = (0x90A3, 0x90B3, 0x90C3, 0x0000, 0x0000, 0x0000, 0x90F3, 0x90E3, 0x90D3, 0x91B3, 0x91C3, 0x0000, 0x0000, 0x91E3, 0x91D3) timing = ('3', '4', '5', '0', '0', '0', '4', '5', '6', '5', '6', '0', '0', '6', '7') else: errors.DoError('badoper', False) return if operand2[0] > 14: errors.DoError('badoper', False) return prebyte = opcode[operand2[0]] // 256 opcbyte = opcode[operand2[0]] % 256 dec.Asm.Timing = timing[operand2[0]] SaveAll(prebyte, opcbyte, operand2)
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()