(
bus: &mut SystemBus,
funct5: u8,
funct3: u8,
addr: u64,
val: u64,
)
| 404 | 0x14 => old_i.max(val_i), // AMOMAX.W |
| 405 | 0x18 => { |
| 406 | let old_u = old_w; |
| 407 | let val_u = val as u32; |
| 408 | old_u.min(val_u) as i32 |
| 409 | } |
| 410 | 0x1C => { |
| 411 | let old_u = old_w; |
| 412 | let val_u = val as u32; |
| 413 | old_u.max(val_u) as i32 |
| 414 | } |
| 415 | _ => return Err(VmError::IllegalInstruction(funct5 as u32)), |
| 416 | }; |
| 417 | |
| 418 | bus.write_word(addr, new_i as u32) |
| 419 | .map_err(|_| VmError::StoreAccessFault(addr))?; |
| 420 | |
| 421 | // Return old value sign-extended |
| 422 | Ok(old_i as i64 as u64) |
| 423 | } else { |
| 424 | // 64-bit AMO |
| 425 | let old = bus |
| 426 | .read_doubleword(addr) |
| 427 | .map_err(|_| VmError::LoadAccessFault(addr))?; |
| 428 | let old_i = old as i64; |
| 429 | let val_i = val as i64; |
| 430 | |
| 431 | let new_val: u64 = match funct5 { |
| 432 | 0x00 => old.wrapping_add(val), // AMOADD.D |
| 433 | 0x01 => val, // AMOSWAP.D |
| 434 | 0x04 => old ^ val, // AMOXOR.D |
| 435 | 0x08 => old | val, // AMOOR.D |
| 436 | 0x0C => old & val, // AMOAND.D |
| 437 | 0x10 => old_i.min(val_i) as u64, // AMOMIN.D |
| 438 | 0x14 => old_i.max(val_i) as u64, // AMOMAX.D |
| 439 | 0x18 => old.min(val), // AMOMINU.D |
| 440 | 0x1C => old.max(val), // AMOMAXU.D |
| 441 | _ => return Err(VmError::IllegalInstruction(funct5 as u32)), |
| 442 | }; |
| 443 | |
| 444 | bus.write_doubleword(addr, new_val) |
| 445 | .map_err(|_| VmError::StoreAccessFault(addr))?; |
| 446 | |
| 447 | Ok(old) |
| 448 | } |
| 449 | } |
no test coverage detected