Skip to content

Commit

Permalink
[cpclib-asm] Fix a crash when handling BANK directive
Browse files Browse the repository at this point in the history
  • Loading branch information
rgiot committed Aug 19, 2023
1 parent c114685 commit 282529a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 9 deletions.
2 changes: 2 additions & 0 deletions cpclib-asm/basm_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ On the code space ($), not physical space ($$)
When used with no argument, a bank corresponds to a memory area outside of the snapshot. All things read&write in memory are thus uncorrelated to the snapshot.
Sections do not apply in a bank.

`BANK page` is similar to `WRITE DIRECT -1 -1 page`

## Labels related

## =
Expand Down
33 changes: 26 additions & 7 deletions cpclib-asm/src/assembler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,17 @@ impl Env {
}
}

fn page_info_for_logical_address_mut(&mut self, address: u16) -> &mut PageInformation {
match &self.selected_bank {
Some(idx) => &mut self.banks[*idx].1, // TODO check if this code is valid
None => {
let active_page =
self.logical_to_physical_address(address).page() as usize;
&mut self.pages_info_sna[active_page]
}
}
}

fn written_bytes(&mut self) -> &mut BitVec {
match &self.selected_bank {
Some(idx) => &mut self.banks[*idx].2,
Expand Down Expand Up @@ -1865,12 +1876,15 @@ impl Env {
Some(exp) => {
// prefix provided, we explicitely want one configuration
let mmr = self.resolve_expr_must_never_fail(exp)?.int()?;

if mmr < 0xC0 || mmr > 0xC7 {
return Err(AssemblerError::MMRError { value: mmr });
}

let mmr = mmr as u8;
self.ga_mmr = mmr;

// we do not change the output address (there is no reason to do that)
}
None => {
// nothing provided, we write in a temporary area
Expand Down Expand Up @@ -3815,6 +3829,7 @@ pub fn assemble_opcode(
}

fn visit_org(address: &Expr, address2: Option<&Expr>, env: &mut Env) -> Result<(), AssemblerError> {

// org $ set org to the output address (cf. rasm)
let code_adr = if address2.is_none() && address == &"$".into() {
if env.start_address().is_none() {
Expand All @@ -3836,18 +3851,21 @@ fn visit_org(address: &Expr, address2: Option<&Expr>, env: &mut Env) -> Result<(
};

// TODO Check overlapping region
let page_info = env.active_page_info_mut();
page_info.logical_outputadr = output_adr as _;
page_info.logical_codeadr = code_adr as _;
page_info.fail_next_write_if_zero = false;
{
let page_info = env.page_info_for_logical_address_mut(output_adr as _);
page_info.logical_outputadr = output_adr as _;
page_info.logical_codeadr = code_adr as _;
page_info.fail_next_write_if_zero = false;
}

// Specify start address at first use
env.active_page_info_mut().startadr = match env.start_address() {
env.page_info_for_logical_address_mut(output_adr as _).startadr = match env.start_address() {
Some(val) => val.min(env.logical_output_address()),
None => env.logical_output_address()
}
.into();


env.output_address = output_adr as _;
env.update_dollar();

Expand All @@ -3865,9 +3883,10 @@ fn visit_org(address: &Expr, address2: Option<&Expr>, env: &mut Env) -> Result<(
file: file!(),
line: line!(),
msg: format!(
"BUG in assembler:{}!= {}",
"BUG in assembler: 0x{:x}!=0x{:x} in pass {:?}",
env.logical_output_address(),
env.logical_output_address()
env.output_address,
env.pass
)
});
}
Expand Down
2 changes: 1 addition & 1 deletion cpclib-asm/src/assembler/page_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub type ProtectedArea = std::ops::RangeInclusive<u16>;
/// A stock CPC 6128 is composed of two pages
#[derive(Debug, Clone)]
pub struct PageInformation {
/// Start adr to use to write binary files. No use when working with snapshots.
/// Start adr to use to write binary files. Not use when working with snapshots.
pub(crate) startadr: Option<u16>,
/// maximum address reached when working with 64k data
pub(crate) maxadr: u16,
Expand Down
2 changes: 1 addition & 1 deletion cpclib-asm/src/implementation/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<'a, E:ExprEvaluationExt> ExprEvaluationExt for UnaryFunctionWrapper<'a,E> {
if arg < 0.into() || arg > 0xFFFF.into() {
return Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
Box::new(AssemblerError::AssemblingError {
msg: format!("Impossible to read memory address {}", arg)
msg: format!("Impossible to read memory address 0x{:X}", arg)
})
)));
}
Expand Down
31 changes: 31 additions & 0 deletions cpclib-basm/tests/asm/good_bank.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
; Set up a unique value in various banks
BANK 0xc0
org 0x4000 + 0
db 0xc0

BANK 0xc4
org 0x4000 + 1
db 0xc4


BANK 0xc5
org 0x4000 + 2
db 0xc5

BANK 0xc6
org 0x4000 + 3
db 0xc6


BANK 0xc7
org 0x4000 + 4
db 0xc7


BANKSET 0
assert memory(0x4000 + 0) == 0xC0

BANKSET 1
assert memory(0x4000 + 2) == 0xC5
assert memory(0x8000 + 3) == 0xC6
assert memory(0xC000 + 4) == 0xC7
30 changes: 30 additions & 0 deletions cpclib-basm/tests/asm/good_write_direct.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
WRITE DIRECT -1, -1, 0xc0
org 0x4000+0
db 0xc0

WRITE DIRECT -1, -1, 0xc4
org 0x4000+1
db 0xc4


WRITE DIRECT -1, -1, 0xc5
org 0x4000+2
db 0xc5

WRITE DIRECT -1, -1, 0xc6
org 0x4000+3
db 0xc6


WRITE DIRECT -1, -1, 0xc7
org 0x4000+4
db 0xc7


BANKSET 0
assert memory(0x4000 + 0) == 0xC0

BANKSET 1
assert memory(0x4000 + 2) == 0xC5
assert memory(0x8000 + 3) == 0xC6
assert memory(0xC000 + 4) == 0xC7

0 comments on commit 282529a

Please sign in to comment.