def CodeWord(data, list="True"): """ Write the code word to the target file. We can't rely on target.CodeWord because that would change everything into RETLW instructions. """ if dec.Asm.Memory != 0 and not dec.Flags.CodeWarn and dec.Asm.Pass == 2: dec.Flags.CodeWarn = True errors.DoWarning('notcode', True) target.SaveByte(data & 0xFF, list) target.SaveByte((data >> 8) & 0xFF, list)
def SaveByte(data, list=True): """ Save byte in code memory. We come here because a directive has generated data to be written in code memory. If we're still below the program size data bytes need to be translated to RETLW instructions. Otherwise a byte has to be stored as a word with high byte 0. Also check whether the end of memory is passed, in which case a warning is issued. """ global Asm, Cross if dec.Asm.Memory == 0: # We only need to do something special inside code memory if dec.Asm.PH_Address > dec.Asm.Max_Address: # We're past the end of program memory. Save as word instead # Temporarily raise program limit to avoid warnings limit = dec.Asm.Max_Address dec.Asm.Max_Address = 0x1FFF # Save a word as usual CodeWord(data & 0xFF, list) # Restore original limit dec.Asm.Max_Address = limit else: # Combine data with RETLW opcode CodeWord(0x3400 + (data & 0xFF), list) # This is an instruction, so it has an execution time dec.Asm.Timing = "2" else: # All other memories can be done as usual target.SaveByte(data, list)
def DirCW(): """ Set the Configuration word. This Configuration word is usually stored at the last location in memory, which is word address $0FFF (or byte addresses ($1FFE and $1FFF). Programming devices expect that word to be there. The SB-Assembler only checks that the Configuration word is stored beyond the program memory. """ global Asm, Cross if dec.Asm.Memory != 0: # The .CW directive can only be used in program memory errors.DoError(dec.Cross.Name + 'codemem', False) return if dec.Asm.PH_Address <= dec.Asm.Max_Address: # We're still in program memory. We can't have that errors.DoError(dec.Cross.Name + 'progmem', False) return if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) config = assem.EvalExpr()[0] if dec.Asm.Pass == 2 and (config < 0 or config > 0x0FFF): # Only 12 bits allowed errors.DoError('range', False) # Temporarily raise program limit limit = dec.Asm.Max_Address dec.Asm.Max_Address = 0x0FFF # Bypass the RETLW pointer target.SaveByte(config & 0xFF) target.SaveByte((config >> 8) & 0x0F) # Restore original limit dec.Asm.Max_Address = limit NoMore()
def CodeWord(data, list="True"): """ Write the code word to the target file. We don't have to anythong special for the PIC16. We only need to do a boundary sync first. """ if dec.Asm.Memory != 0 and not dec.Flags.CodeWarn and dec.Asm.Pass == 2: # It's useless to store program code in EEPROM or RAM memory dec.Flags.CodeWarn = True errors.DoWarning('notcode', True) if dec.Asm.Memory == 0: # OK, we're in code memory if (dec.Asm.PH_Address % 2) != 0: # We're at an odd address. Let's save a padding byte target.SaveByte(0, False) dec.Asm.BOL_Address = dec.Asm.PH_Address dec.Asm.List_Address = dec.Asm.PH_Address target.SaveByte(data & 0xFF, list) target.SaveByte((data >> 8) & 0xFF, list)
def DirID(): """ Set the ID words. These ID words are usually stored directly behind the program memory, or directly behind the EEPROM memory if that is present. The SB-Assembler only checks that the Configuration word is stored beyond the program memory. """ global Asm, Cross if dec.Asm.Memory != 0: # The .ID directive can only be used in program memory errors.DoError(dec.Cross.Name + 'codemem', False) return if dec.Asm.PH_Address <= dec.Asm.Max_Address: # We're still in program memory. We can't have that errors.DoError(dec.Cross.Name + 'progmem', False) return if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) id = assem.EvalExpr()[0] # Temporarily raise program limit limit = dec.Asm.Max_Address dec.Asm.Max_Address = 0x0FFF # Save the ID, one nibble at a time target.SaveByte(id & 0x000F) target.SaveByte(0) target.SaveByte((id >> 4) & 0x000F) target.SaveByte(0) target.SaveByte((id >> 8) & 0x000F) target.SaveByte(0) target.SaveByte((id >> 12) & 0x000F) target.SaveByte(0) # Restore original limit dec.Asm.Max_Address = limit NoMore()
def BincHEX(line): """ Parse a plain HEX line. This one's easy. """ for i in range(0, len(line), 2): # Translate each hex digit pair into a byte value = HexPair(line[i:i+2]) if not value[0]: target.SaveByte(value[1], False) else: return True return False
def DirID(): """ Set the ID words. These ID words are usually at word location $000 to $8003. The SB-Assembler only checks that the Configuration word is stored beyond the program memory. ID words can only store the 7 least significant bits. The SB-Assembler does not check the range. It simply truncates to 7 bits. """ global Asm, Cross id2 = 0 id3 = 0 id4 = 0 if dec.Asm.Memory != 0: # The .ID directive can only be used in program memory errors.DoError(dec.Cross.Name + 'codemem', False) return if dec.Asm.PH_Address <= dec.Asm.Max_Address: # We're still in program memory. We can't have that errors.DoError(dec.Cross.Name + 'progmem', False) return if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) id1 = assem.EvalExpr()[0] if assem.MoreParameters(): # More than 1 ID word are given if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) id2 = assem.EvalExpr()[0] if assem.MoreParameters(): # More than 2 ID word are given if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) id3 = assem.EvalExpr()[0] if assem.MoreParameters(): # More than 1 ID word are given if assem.NowChar() == '#': # Ignore the # symbol assem.NowChar(True) id4 = assem.EvalExpr()[0] # Temporarily raise program limit limit = dec.Asm.Max_Address dec.Asm.Max_Address = 0x1FFFF # Save the ID, one nibble at a time target.SaveByte(id1 & 0x007F) target.SaveByte(0) target.SaveByte(id2 & 0x007F) target.SaveByte(0) target.SaveByte(id3 & 0x007F) target.SaveByte(0) target.SaveByte(id4 & 0x007F) target.SaveByte(0) # Restore original limit dec.Asm.Max_Address = limit NoMore()