fixing very sneaky bug

This commit is contained in:
Jakub Doka 2024-11-04 12:38:47 +01:00
parent e8f1d2af8c
commit 2e36f32ae0
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
8 changed files with 286 additions and 75 deletions

View file

@ -593,6 +593,59 @@ main := fn(): uint {
### Purely Testing Examples ### Purely Testing Examples
#### inlining_issues
```hb
main := fn(): void {
@use("main.hb").put_filled_rect(.(&.(0), 100, 100), .(0, 0), .(0, 0), .(1))
}
// in module: memory.hb
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(8, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}
// in module: main.hb
Color := struct {r: u8}
Vec2 := fn($Ty: type): type return struct {x: Ty, y: Ty}
memory := @use("memory.hb")
Surface := struct {
buf: ^Color,
width: uint,
height: uint,
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + y * surface.width + x
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
rows_to_fill -= 2
}
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
}
return
}
```
#### only_break_loop #### only_break_loop
```hb ```hb
memory := @use("memory.hb") memory := @use("memory.hb")

View file

@ -39,7 +39,7 @@ const GLOBAL_ACLASS: usize = 1;
pub mod hbvm; pub mod hbvm;
type Nid = u16; type Nid = u16;
type AClassId = u16; type AClassId = i16;
type Lookup = crate::ctx_map::CtxMap<Nid>; type Lookup = crate::ctx_map::CtxMap<Nid>;
@ -410,6 +410,7 @@ impl Nodes {
} }
fn bind(&mut self, from: Nid, to: Nid) { fn bind(&mut self, from: Nid, to: Nid) {
debug_assert_ne!(to, 0);
self[from].outputs.push(to); self[from].outputs.push(to);
self[to].inputs.push(from); self[to].inputs.push(from);
} }
@ -512,17 +513,16 @@ impl Nodes {
if node.ty != ty::Id::VOID { if node.ty != ty::Id::VOID {
writeln!( writeln!(
out, out,
" node{i}[label=\"{i} {} {} {} {}\" color={color}]", " node{i}[label=\"{i} {} {} {}\" color={color}]",
node.kind, node.kind,
ty::Display::new(tys, files, node.ty), ty::Display::new(tys, files, node.ty),
node.aclass, node.aclass,
node.mem,
)?; )?;
} else { } else {
writeln!( writeln!(
out, out,
" node{i}[label=\"{i} {} {} {}\" color={color}]", " node{i}[label=\"{i} {} {}\" color={color}]",
node.kind, node.aclass, node.mem, node.kind, node.aclass,
)?; )?;
} }
@ -763,7 +763,21 @@ impl Nodes {
} }
pub fn aclass_index(&self, region: Nid) -> (usize, Nid) { pub fn aclass_index(&self, region: Nid) -> (usize, Nid) {
(self[region].aclass as _, self[region].mem) if self[region].aclass >= 0 {
(self[region].aclass as _, region)
} else {
(
self[self[region].aclass.unsigned_abs() - 1].aclass as _,
self[region].aclass.unsigned_abs() - 1,
)
}
}
fn pass_aclass(&mut self, from: Nid, to: Nid) {
debug_assert!(self[from].aclass >= 0);
if from != to {
self[to].aclass = -(from as AClassId + 1);
}
} }
fn peephole(&mut self, target: Nid) -> Option<Nid> { fn peephole(&mut self, target: Nid) -> Option<Nid> {
@ -1335,7 +1349,7 @@ impl Nodes {
write!(out, " {node:>2}-c{:>2}: ", self[node].ralloc_backref)?; write!(out, " {node:>2}-c{:>2}: ", self[node].ralloc_backref)?;
} }
match self[node].kind { match self[node].kind {
Kind::Assert { .. } | Kind::Start => unreachable!(), Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind),
Kind::End => return Ok(()), Kind::End => return Ok(()),
Kind::If => write!(out, " if: "), Kind::If => write!(out, " if: "),
Kind::Region | Kind::Loop => writeln!(out, " goto: {node}"), Kind::Region | Kind::Loop => writeln!(out, " goto: {node}"),
@ -1499,6 +1513,10 @@ impl Nodes {
log::error!("is unreachable but still present {id} {:?}", node.kind); log::error!("is unreachable but still present {id} {:?}", node.kind);
failed = true; failed = true;
} }
if node.outputs.contains(&id) && !matches!(node.kind, Kind::Loop | Kind::End) {
log::error!("node depends on it self and its not a loop {id} {:?}", node);
failed = true;
}
} }
if failed { if failed {
@ -1522,8 +1540,8 @@ impl Nodes {
let lvalue = lvar.value(); let lvalue = lvar.value();
let inps = [node, lvalue, VOID]; let inps = [node, lvalue, VOID];
lvar.set_value(self.new_node_nop(lvar.ty, Kind::Phi, inps), self); lvar.set_value(self.new_node_nop(lvar.ty, Kind::Phi, inps), self);
self[lvar.value()].aclass = self[lvalue].aclass;
self[lvar.value()].mem = self[lvalue].mem; self.pass_aclass(self.aclass_index(lvalue).1, lvar.value());
} }
var.set_value(lvar.value(), self); var.set_value(lvar.value(), self);
} }
@ -1728,7 +1746,6 @@ pub struct Node {
lock_rc: LockRc, lock_rc: LockRc,
loop_depth: LoopDepth, loop_depth: LoopDepth,
aclass: AClassId, aclass: AClassId,
mem: Nid,
antidep: Nid, antidep: Nid,
} }
@ -2254,7 +2271,6 @@ impl<'a> Codegen<'a> {
fn new_stack(&mut self, ty: ty::Id) -> Nid { fn new_stack(&mut self, ty: ty::Id) -> Nid {
let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]); let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]);
self.ci.nodes[stck].aclass = self.ci.scope.aclasses.len() as _; self.ci.nodes[stck].aclass = self.ci.scope.aclasses.len() as _;
self.ci.nodes[stck].mem = stck;
self.ci.scope.aclasses.push(AClass::new(&mut self.ci.nodes)); self.ci.scope.aclasses.push(AClass::new(&mut self.ci.nodes));
stck stck
} }
@ -2271,25 +2287,46 @@ impl<'a> Codegen<'a> {
let (value_index, value_region) = self.ci.nodes.aclass_index(value); let (value_index, value_region) = self.ci.nodes.aclass_index(value);
if value_index != 0 { if value_index != 0 {
// simply switch the class to the default one self.ci.nodes[value_region].aclass = 0;
let aclass = &mut self.ci.scope.aclasses[value_index]; //// simply switch the class to the default one
self.ci.nodes.load_loop_aclass(value_index, aclass, &mut self.ci.loops); //let aclass = &mut self.ci.scope.aclasses[value_index];
let last_store = aclass.last_store.get(); //self.ci.nodes.load_loop_aclass(value_index, aclass, &mut self.ci.loops);
let mut cursor = last_store; //let last_store = aclass.last_store.get();
let mut first_store = cursor; //let mut cursor = last_store;
while cursor != MEM { //let mut first_store = cursor;
first_store = cursor; //while cursor != MEM {
cursor = self.ci.nodes[cursor].inputs[3]; // first_store = cursor;
} // debug_assert_matches!(
// self.ci.nodes[cursor].kind,
// Kind::Stre,
// "{:?}",
// self.ci.nodes[cursor]
// );
// cursor = self.ci.nodes[cursor].inputs[3];
//}
if last_store != MEM { //if last_store != MEM {
// let base_class = self.ci.scope.aclasses[0].last_store.get();
// if base_class != MEM {
// self.ci.nodes.modify_input(first_store, 3, base_class);
// }
// self.ci.scope.aclasses[0].last_store.set(last_store, &mut self.ci.nodes);
//}
self.ci.nodes.load_loop_aclass(0, &mut self.ci.scope.aclasses[0], &mut self.ci.loops);
self.ci.nodes.load_loop_aclass(
value_index,
&mut self.ci.scope.aclasses[value_index],
&mut self.ci.loops,
);
let base_class = self.ci.scope.aclasses[0].last_store.get(); let base_class = self.ci.scope.aclasses[0].last_store.get();
if base_class != MEM { let last_store = self.ci.scope.aclasses[value_index].last_store.get();
self.ci.nodes.modify_input(first_store, 3, base_class); if base_class != MEM && last_store != MEM {
self.ci.nodes.bind(base_class, last_store);
} }
if last_store != MEM {
self.ci.scope.aclasses[0].last_store.set(last_store, &mut self.ci.nodes); self.ci.scope.aclasses[0].last_store.set(last_store, &mut self.ci.nodes);
} }
self.ci.nodes[value_region].aclass = 0;
} }
let (index, _) = self.ci.nodes.aclass_index(region); let (index, _) = self.ci.nodes.aclass_index(region);
@ -2485,8 +2522,10 @@ impl<'a> Codegen<'a> {
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]); let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() { for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() {
self.ci.nodes.load_loop_aclass(i, aclass, &mut self.ci.loops); self.ci.nodes.load_loop_aclass(i, aclass, &mut self.ci.loops);
if aclass.last_store.get() != MEM {
inps.push(aclass.last_store.get()); inps.push(aclass.last_store.get());
} }
}
self.ci.ctrl.set( self.ci.ctrl.set(
self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Return, inps), self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Return, inps),
@ -2729,12 +2768,11 @@ impl<'a> Codegen<'a> {
let mut rhs = rhs?; let mut rhs = rhs?;
self.strip_var(&mut rhs); self.strip_var(&mut rhs);
self.unwrap_opt(right.pos(), &mut rhs); self.unwrap_opt(right.pos(), &mut rhs);
let (ty, aclass, mem) = self.binop_ty(pos, &mut lhs, &mut rhs, op); let (ty, aclass) = self.binop_ty(pos, &mut lhs, &mut rhs, op);
let inps = [VOID, lhs.id, rhs.id]; let inps = [VOID, lhs.id, rhs.id];
let bop = let bop =
self.ci.nodes.new_node_lit(ty.bin_ret(op), Kind::BinOp { op }, inps); self.ci.nodes.new_node_lit(ty.bin_ret(op), Kind::BinOp { op }, inps);
self.ci.nodes[bop.id].aclass = aclass as _; self.ci.nodes.pass_aclass(aclass, bop.id);
self.ci.nodes[bop.id].mem = mem;
Some(bop) Some(bop)
} }
ty::Kind::Struct(s) if op.is_homogenous() => { ty::Kind::Struct(s) if op.is_homogenous() => {
@ -2784,12 +2822,11 @@ impl<'a> Codegen<'a> {
let inps = [VOID, idx.id, size]; let inps = [VOID, idx.id, size];
let offset = let offset =
self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Mul }, inps); self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Mul }, inps);
let (aclass, mem) = self.ci.nodes.aclass_index(bs.id); let aclass = self.ci.nodes.aclass_index(bs.id).1;
let inps = [VOID, bs.id, offset]; let inps = [VOID, bs.id, offset];
let ptr = let ptr =
self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Add }, inps); self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Add }, inps);
self.ci.nodes[ptr].aclass = aclass as _; self.ci.nodes.pass_aclass(aclass, ptr);
self.ci.nodes[ptr].mem = mem;
Some(Value::ptr(ptr).ty(elem)) Some(Value::ptr(ptr).ty(elem))
} }
@ -3896,11 +3933,10 @@ impl<'a> Codegen<'a> {
} }
let off = self.ci.nodes.new_const(ty::Id::INT, off); let off = self.ci.nodes.new_const(ty::Id::INT, off);
let (aclass, mem) = self.ci.nodes.aclass_index(val); let aclass = self.ci.nodes.aclass_index(val).1;
let inps = [VOID, val, off]; let inps = [VOID, val, off];
let seted = self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Add }, inps); let seted = self.ci.nodes.new_node(ty::Id::INT, Kind::BinOp { op: TokenKind::Add }, inps);
self.ci.nodes[seted].aclass = aclass as _; self.ci.nodes.pass_aclass(aclass, seted);
self.ci.nodes[seted].mem = mem;
seted seted
} }
@ -4089,7 +4125,7 @@ impl<'a> Codegen<'a> {
lhs: &mut Value, lhs: &mut Value,
rhs: &mut Value, rhs: &mut Value,
op: TokenKind, op: TokenKind,
) -> (ty::Id, usize, Nid) { ) -> (ty::Id, Nid) {
if let Some(upcasted) = lhs.ty.try_upcast(rhs.ty) { if let Some(upcasted) = lhs.ty.try_upcast(rhs.ty) {
let to_correct = if lhs.ty != upcasted { let to_correct = if lhs.ty != upcasted {
Some((lhs, rhs)) Some((lhs, rhs))
@ -4111,20 +4147,16 @@ impl<'a> Codegen<'a> {
self.ci.nodes.new_node(upcasted, Kind::BinOp { op: TokenKind::Mul }, [ self.ci.nodes.new_node(upcasted, Kind::BinOp { op: TokenKind::Mul }, [
VOID, oper.id, cnst, VOID, oper.id, cnst,
]); ]);
return ( return (upcasted, self.ci.nodes.aclass_index(other.id).1);
upcasted,
self.ci.nodes[other.id].aclass as _,
self.ci.nodes[other.id].mem,
);
} }
} }
(upcasted, DEFAULT_ACLASS, VOID) (upcasted, VOID)
} else { } else {
let ty = self.ty_display(lhs.ty); let ty = self.ty_display(lhs.ty);
let expected = self.ty_display(rhs.ty); let expected = self.ty_display(rhs.ty);
self.report(pos, fa!("'{ty} {op} {expected}' is not supported")); self.report(pos, fa!("'{ty} {op} {expected}' is not supported"));
(ty::Id::NEVER, DEFAULT_ACLASS, VOID) (ty::Id::NEVER, VOID)
} }
} }
@ -4448,6 +4480,7 @@ mod tests {
fb_driver; fb_driver;
// Purely Testing Examples; // Purely Testing Examples;
inlining_issues;
null_check_test; null_check_test;
only_break_loop; only_break_loop;
reading_idk; reading_idk;

View file

@ -395,6 +395,9 @@ impl ItemCtx {
PLoc::WideReg(rg, size) => (rg, size), PLoc::WideReg(rg, size) => (rg, size),
PLoc::Ref(..) | PLoc::Reg(..) => continue, PLoc::Ref(..) | PLoc::Reg(..) => continue,
}; };
if size > 8 {
allocs.next().unwrap();
}
self.emit(instrs::ld(rg, atr(arg), 0, size)); self.emit(instrs::ld(rg, atr(arg), 0, size));
} }
@ -946,7 +949,7 @@ impl<'a> Function<'a> {
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
)); ));
} }
PLoc::WideReg(..) | PLoc::Reg(..) => { PLoc::WideReg(r, size) | PLoc::Reg(r, size) => {
loop { loop {
match self.nodes[i].kind { match self.nodes[i].kind {
Kind::Stre { .. } => i = self.nodes[i].inputs[2], Kind::Stre { .. } => i = self.nodes[i].inputs[2],
@ -956,7 +959,16 @@ impl<'a> Function<'a> {
debug_assert_ne!(i, 0); debug_assert_ne!(i, 0);
} }
debug_assert!(i != 0); debug_assert!(i != 0);
ops.push(self.urg(i)); ops.push(regalloc2::Operand::reg_fixed_use(
self.rg(i),
regalloc2::PReg::new(r as _, regalloc2::RegClass::Int),
));
if size > 8 {
ops.push(regalloc2::Operand::reg_fixed_use(
self.rg(i),
regalloc2::PReg::new((r + 1) as _, regalloc2::RegClass::Int),
));
}
} }
PLoc::Ref(r, _) => { PLoc::Ref(r, _) => {
loop { loop {
@ -1044,6 +1056,7 @@ impl<'a> Function<'a> {
} }
Kind::Stre if node.inputs[1] == VOID => self.nodes.lock(nid), Kind::Stre if node.inputs[1] == VOID => self.nodes.lock(nid),
Kind::Stre => { Kind::Stre => {
debug_assert_ne!(self.tys.size_of(node.ty), 0);
let mut region = node.inputs[2]; let mut region = node.inputs[2];
if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add }) if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
&& self.nodes.is_const(self.nodes[region].inputs[2]) && self.nodes.is_const(self.nodes[region].inputs[2])
@ -1597,6 +1610,7 @@ pub fn test_run_vm(out: &[u8], output: &mut String) {
unsafe { alloc::alloc::dealloc(ptr as *mut u8, layout) }; unsafe { alloc::alloc::dealloc(ptr as *mut u8, layout) };
} }
3 => vm.write_reg(1, 42), 3 => vm.write_reg(1, 42),
8 => {}
unknown => unreachable!("unknown ecall: {unknown:?}"), unknown => unreachable!("unknown ecall: {unknown:?}"),
}, },
Ok(hbvm::VmRunOk::Timer) => { Ok(hbvm::VmRunOk::Timer) => {

View file

@ -8,12 +8,13 @@ main:
LI64 r6, 6d LI64 r6, 6d
LI64 r5, 5d LI64 r5, 5d
LI64 r2, 1d LI64 r2, 1d
LD r3, r4, 0a, 16h CP r3, r4
LD r3, r3, 0a, 16h
ECA ECA
LI64 r1, 0d LI64 r1, 0d
ADDI64 r254, r254, 16d ADDI64 r254, r254, 16d
JALA r0, r31, 0a JALA r0, r31, 0a
ev: Ecall ev: Ecall
code size: 152 code size: 155
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -24,14 +24,14 @@ scalar_values:
structs: structs:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
LI64 r1, 5d LI64 r1, 5d
ST r1, r254, 0a, 8h ST r1, r254, 16a, 8h
ST r1, r254, 8a, 8h ST r1, r254, 24a, 8h
LD r5, r254, 0a, 8h LD r5, r254, 16a, 8h
ADDI64 r7, r5, 15d ADDI64 r7, r5, 15d
ST r7, r254, 16a, 8h ST r7, r254, 0a, 8h
LI64 r10, 20d LI64 r10, 20d
ST r10, r254, 24a, 8h ST r10, r254, 8a, 8h
LD r1, r254, 16a, 8h LD r1, r254, 0a, 8h
SUB64 r1, r1, r10 SUB64 r1, r1, r10
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -0,0 +1,109 @@
main:
ADDI64 r254, r254, -66d
ST r31, r254, 58a, 8h
ADDI64 r3, r254, 33d
ADDI64 r2, r254, 34d
ADDI64 r6, r254, 1d
LI64 r9, 0d
ADDI64 r4, r254, 17d
ST r3, r254, 34a, 8h
LI64 r10, 100d
ADDI64 r7, r254, 0d
LI8 r5, 1b
ST r9, r254, 1a, 8h
ST r9, r254, 17a, 8h
ST r10, r254, 42a, 8h
LI8 r3, 0b
ST r5, r254, 0a, 1h
ST r9, r254, 9a, 8h
ST r9, r254, 25a, 8h
ST r10, r254, 50a, 8h
ST r3, r254, 33a, 1h
CP r3, r4
CP r5, r6
LD r3, r3, 0a, 16h
LD r5, r5, 0a, 16h
LD r7, r7, 0a, 1h
JAL r31, r0, :put_filled_rect
LD r31, r254, 58a, 8h
ADDI64 r254, r254, 66d
JALA r0, r31, 0a
put_filled_rect:
ADDI64 r254, r254, -212d
ST r32, r254, 108a, 104h
ST r3, r254, 92a, 16h
ADDI64 r3, r254, 92d
ST r5, r254, 76a, 16h
ADDI64 r5, r254, 76d
ST r7, r254, 75a, 1h
ADDI64 r7, r254, 75d
LI64 r8, 25d
LI64 r32, 2d
LI64 r6, 8d
ADDI64 r33, r254, 25d
ADDI64 r34, r254, 50d
LI8 r35, 5b
ST r35, r254, 25a, 1h
LD r36, r5, 0a, 8h
ST r36, r254, 26a, 4h
LI64 r37, 1d
ST r37, r254, 30a, 4h
ST r7, r254, 34a, 8h
ST r35, r254, 50a, 1h
ST r36, r254, 51a, 4h
ST r37, r254, 55a, 4h
ST r7, r254, 59a, 8h
CP r38, r7
LD r7, r3, 8a, 8h
LD r39, r5, 8a, 8h
ADD64 r11, r39, r7
SUB64 r4, r11, r37
LD r40, r2, 8a, 8h
MUL64 r5, r40, r4
LD r9, r2, 0a, 8h
ADD64 r10, r9, r5
LD r2, r3, 0a, 8h
ADD64 r41, r2, r10
MUL64 r3, r40, r7
ADD64 r4, r9, r3
ADD64 r42, r2, r4
3: JGTU r39, r37, :0
JNE r39, r37, :1
ADDI64 r4, r254, 0d
ST r35, r254, 0a, 1h
ST r36, r254, 1a, 4h
ST r37, r254, 5a, 4h
ST r38, r254, 9a, 8h
ST r42, r254, 17a, 8h
CP r2, r6
CP r3, r32
CP r5, r8
ECA
JMP :1
1: JMP :2
0: CP r3, r32
CP r43, r6
CP r44, r8
ST r42, r254, 67a, 8h
CP r2, r43
CP r4, r34
CP r5, r44
ECA
ST r41, r254, 42a, 8h
CP r2, r43
CP r3, r32
CP r4, r33
CP r5, r44
ECA
ADD64 r42, r40, r42
SUB64 r41, r41, r40
SUB64 r39, r39, r32
CP r6, r43
CP r8, r44
JMP :3
2: LD r32, r254, 108a, 104h
ADDI64 r254, r254, 212d
JALA r0, r31, 0a
code size: 917
ret: 0
status: Ok(())

View file

@ -20,12 +20,12 @@ main:
LI8 r35, 1b LI8 r35, 1b
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :4 JNE r1, r0, :4
ST r35, r254, 56a, 1h ST r35, r254, 40a, 1h
LD r9, r33, 0a, 8h LD r9, r33, 0a, 8h
ST r9, r254, 64a, 8h ST r9, r254, 48a, 8h
JMP :5 JMP :5
4: ST r34, r254, 56a, 1h 4: ST r34, r254, 40a, 1h
5: LD r6, r254, 56a, 1h 5: LD r6, r254, 40a, 1h
ANDI r6, r6, 255d ANDI r6, r6, 255d
ANDI r34, r34, 255d ANDI r34, r34, 255d
JEQ r6, r34, :6 JEQ r6, r34, :6
@ -48,34 +48,34 @@ main:
LI64 r37, 1d LI64 r37, 1d
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :10 JNE r1, r0, :10
ST r3, r254, 16a, 8h ST r3, r254, 0a, 8h
JMP :11 JMP :11
10: ST r32, r254, 16a, 8h 10: ST r32, r254, 0a, 8h
ST r37, r254, 24a, 8h ST r37, r254, 8a, 8h
ST r37, r254, 72a, 8h ST r37, r254, 72a, 8h
11: LD r2, r254, 16a, 8h 11: LD r2, r254, 0a, 8h
JNE r2, r3, :12 JNE r2, r3, :12
LI64 r1, 34d LI64 r1, 34d
JMP :3 JMP :3
12: JAL r31, r0, :decide 12: JAL r31, r0, :decide
ADDI64 r10, r254, 32d ADDI64 r10, r254, 16d
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :13 JNE r1, r0, :13
ADDI64 r11, r254, 0d ADDI64 r11, r254, 56d
ST r32, r254, 0a, 8h ST r32, r254, 56a, 8h
ST r37, r254, 8a, 8h ST r37, r254, 64a, 8h
ST r35, r254, 32a, 1h ST r35, r254, 16a, 1h
ADDI64 r12, r10, 8d ADDI64 r12, r10, 8d
BMC r11, r12, 16h BMC r11, r12, 16h
JMP :14 JMP :14
13: ST r34, r254, 32a, 1h 13: ST r34, r254, 16a, 1h
14: LD r11, r254, 32a, 1h 14: LD r11, r254, 16a, 1h
ANDI r11, r11, 255d ANDI r11, r11, 255d
ANDI r34, r34, 255d ANDI r34, r34, 255d
JEQ r11, r34, :15 JEQ r11, r34, :15
LI64 r1, 420d LI64 r1, 420d
JMP :3 JMP :3
15: LD r5, r254, 16a, 8h 15: LD r5, r254, 0a, 8h
LD r7, r5, 0a, 8h LD r7, r5, 0a, 8h
ANDI r9, r36, 65535d ANDI r9, r36, 65535d
SUB64 r1, r9, r7 SUB64 r1, r9, r7

View file

@ -1,13 +1,14 @@
main: main:
ADDI64 r254, r254, -56d ADDI64 r254, r254, -56d
ST r31, r254, 32a, 24h ST r31, r254, 32a, 24h
LI64 r3, 4d LI64 r2, 4d
ADDI64 r2, r254, 16d ADDI64 r4, r254, 16d
ST r3, r254, 16a, 8h ST r2, r254, 16a, 8h
LI64 r32, 3d LI64 r32, 3d
ST r32, r254, 24a, 8h ST r32, r254, 24a, 8h
ADDI64 r33, r254, 0d ADDI64 r33, r254, 0d
LD r3, r2, 0a, 16h CP r3, r4
LD r3, r3, 0a, 16h
JAL r31, r0, :odher_pass JAL r31, r0, :odher_pass
ST r1, r254, 0a, 16h ST r1, r254, 0a, 16h
LD r2, r254, 8a, 8h LD r2, r254, 8a, 8h
@ -29,6 +30,6 @@ odher_pass:
pass: pass:
LD r1, r2, 0a, 8h LD r1, r2, 0a, 8h
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 305 code size: 308
ret: 4 ret: 4
status: Ok(()) status: Ok(())