Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
abirvalarg committed Dec 29, 2021
2 parents 9d3f154 + 08e19eb commit 17c2c07
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 312 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@ tags
[._]*.un~

# End of https://www.toptal.com/developers/gitignore/api/rust,vim,linux,git

test.*
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pic12asm"
version = "1.0.0"
version = "1.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ You can use all instructions from the datasheet. Labels can be defined by adding

At this point you can only compile 1 file. Hopefully, it won't be a big problem because of limited resources of the platform.

There's 1 additional preudo-instruction `DATA k`. Corresponding word in ROM will be set to the number `k`.
### Pseudo-instructions
#### `DATA`
The `DATA k` pseudo-instruction is replaced by value `k`, made for instrrupt vector.

#### `BANK`
This instruction tells assembler to fill current bank with `NOP`s and go to the next bank of ROM. Attempt to go to next bank without this instruction will cause an error.

### Build
to build a file use following comand:
```bash
pic12asm input.asm output.bin
Expand Down Expand Up @@ -56,4 +62,4 @@ isSet:
- Tested only with PIC12F509
- Register names don't work yet, will be fixed in future versions
- Destination select is always required if supported by instruction
- Assembler doesn't check for incorrect values
- Assembler doesn't check for all incorrect values
9 changes: 9 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,12 @@ impl fmt::Display for BadOpArgs {
}
}
impl Error for BadOpArgs {}

#[derive(Debug)]
pub struct DoesnotFit(pub usize);
impl fmt::Display for DoesnotFit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Instruction on line {} doesn't fit in memory bank", self.0)
}
}
impl Error for DoesnotFit {}
265 changes: 265 additions & 0 deletions src/instructions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
use phf::phf_map;
use std::collections::HashMap;
use crate::util::get_num;
use crate::error::*;

type OpDecoder = dyn Fn(&HashMap<&str, usize>, Option<&str>, Option<&str>, usize) -> Result<[u8; 2], Box<dyn std::error::Error>>;
pub const OP_CODES: phf::Map<&'static str, &OpDecoder> = phf_map! {
"ADDWF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8;
let d = get_num(d.unwrap(), lbl)? as u8;
Ok([0b1100_0000 | ((d & 1) << 5) | (f & 0b11111), 0b0001])
}
}),
"ANDWF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8;
let d = get_num(d.unwrap(), lbl)? as u8;
Ok([0b0100_0000 | ((d & 1) << 5) | (f & 0b11111), 0b0001])
}
}),
"CLRF" => &(|lbl, f, _, l| {
if f == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8;
Ok([0b0110_0000 | (f & 0b11111), 0])
}
}),
"CLRW" => &(|_, _, _, _| {
Ok([0b0100_0000, 0b0000])
}),
"COMF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b0100_0000 | f | (d << 5), 0b0010])
}
}),
"DECF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1100_0000 | f | (d << 5), 0b0000])
}
}),
"DECFSZ" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1100_0000 | f | (d << 5), 0b0010])
}
}),
"INCF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1000_0000 | f | (d << 5), 0b0010])
}
}),
"INCFSZ" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1100_0000 | f | (d << 5), 0b0011])
}
}),
"IORWF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b0000_0000 | f | (d << 5), 0b0001])
}
}),
"MOVF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b0000_0000 | f | (d << 5), 0b0010])
}
}),
"MOVWF" => &(|lbl, f, _, l| {
if f == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
Ok([0b0010_0000 | f, 0b0000])
}
}),
"NOP" => &(|_, _, _, _| { Ok([0, 0]) }),
"RLF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b0100_0000 | f | (d << 5), 0b0011])
}
}),
"RRF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b0000_0000 | f | (d << 5), 0b0011])
}
}),
"SUBWF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1000_0000 | f | (d << 5), 0b0000])
}
}),
"SWAPF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1000_0000 | f | (d << 5), 0b0011])
}
}),
"XORWF" => &(|lbl, f, d, l| {
if f == None || d == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let d = get_num(d.unwrap(), lbl)? as u8 & 0b1;
Ok([0b1000_0000 | f | (d << 5), 0b0001])
}
}),
"BCF" => &(|lbl, f, b, l| {
if f == None || b == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let b = get_num(b.unwrap(), lbl)? as u8 & 0b111;
Ok([f | (b << 5), 0b0100])
}
}),
"BSF" => &(|lbl, f, b, l| {
if f == None || b == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let b = get_num(b.unwrap(), lbl)? as u8 & 0b111;
Ok([f | (b << 5), 0b0101])
}
}),
"BTFSC" => &(|lbl, f, b, l| {
if f == None || b == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let b = get_num(b.unwrap(), lbl)? as u8 & 0b111;
Ok([f | (b << 5), 0b0110])
}
}),
"BTFSS" => &(|lbl, f, b, l| {
if f == None || b == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b11111;
let b = get_num(b.unwrap(), lbl)? as u8 & 0b111;
Ok([f | (b << 5), 0b0111])
}
}),
"ANDLW" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1110])
}
}),
"CALL" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1001])
}
}),
"CLRWDT" => &(|_, _, _, _| { Ok([0b0100, 0]) }),
"GOTO" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u16 & 0x1ff;
Ok([(k & 0xff) as u8, (0b1010 | (k >> 8)) as u8])
}
}),
"IORLW" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1101])
}
}),
"MOVLW" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1100])
}
}),
"OPTION" => &(|_, _, _, _| { Ok([0b0010, 0]) }),
"RETLW" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1000])
}
}),
"SLEEP" => &(|_, _, _, _| { Ok([0b0011, 0]) }),
"TRIS" => &(|lbl, f, _, l| {
if f == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let f = get_num(f.unwrap(), lbl)? as u8 & 0b0111;
Ok([f, 0b0000])
}
}),
"XORLW" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u8 & 0xff;
Ok([k, 0b1111])
}
}),
"DATA" => &(|lbl, k, _, l| {
if k == None {
Err(Box::new(BadOpArgs(l + 1)))
} else {
let k = get_num(k.unwrap(), lbl)? as u16 & 0x0fff;
Ok([(k & 0xff) as u8, (k >> 8) as u8])
}
})
};
Loading

0 comments on commit 17c2c07

Please sign in to comment.