| ... | ... | @@ -446,6 +446,32 @@ pub const Instruction = union(enum) { |
| 446 | 446 | rs2: u5, |
| 447 | 447 | }, |
| 448 | 448 | |
| 449 | pub const CCR = enum(u3) { |
| 450 | fcc0, |
| 451 | fcc1, |
| 452 | fcc2, |
| 453 | fcc3, |
| 454 | icc, |
| 455 | reserved1, |
| 456 | xcc, |
| 457 | reserved2, |
| 458 | }; |
| 459 | |
| 460 | pub const RCondition = enum(u3) { |
| 461 | reserved1, |
| 462 | eq_zero, |
| 463 | le_zero, |
| 464 | lt_zero, |
| 465 | reserved, |
| 466 | ne_zero, |
| 467 | gt_zero, |
| 468 | ge_zero, |
| 469 | }; |
| 470 | |
| 471 | // TODO: Need to define an enum for `cond` values |
| 472 | // This is kinda challenging since the cond values have different meanings |
| 473 | // depending on whether it's operating on integer or FP CCR. |
| 474 | |
| 449 | 475 | pub fn toU32(self: Instruction) u32 { |
| 450 | 476 | return @bitCast(u32, self); |
| 451 | 477 | } |
| ... | ... | @@ -462,17 +488,16 @@ pub const Instruction = union(enum) { |
| 462 | 488 | } |
| 463 | 489 | |
| 464 | 490 | fn format2a(rd: Register, op2: u3, imm: i22) Instruction { |
| 465 | | const umm = @bitCast(u22, imm); |
| 466 | 491 | return Instruction{ |
| 467 | 492 | .format_2a = .{ |
| 468 | 493 | .rd = rd.enc(), |
| 469 | 494 | .op2 = op2, |
| 470 | | .imm22 = umm, |
| 495 | .imm22 = @bitCast(u22, imm), |
| 471 | 496 | }, |
| 472 | 497 | }; |
| 473 | 498 | } |
| 474 | 499 | |
| 475 | | fn format2b(a: u1, cond: u4, op2: u3, disp: i24) Instruction { |
| 500 | fn format2b(annul: bool, cond: u4, op2: u3, disp: i24) Instruction { |
| 476 | 501 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 477 | 502 | assert(disp % 4 == 0); |
| 478 | 503 | |
| ... | ... | @@ -480,7 +505,7 @@ pub const Instruction = union(enum) { |
| 480 | 505 | const udisp = @truncate(u22, @bitCast(u24, disp) >> 2); |
| 481 | 506 | return Instruction{ |
| 482 | 507 | .format_2b = .{ |
| 483 | | .a = a, |
| 508 | .a = @boolToInt(annul), |
| 484 | 509 | .cond = cond, |
| 485 | 510 | .op2 = op2, |
| 486 | 511 | .disp22 = udisp, |
| ... | ... | @@ -488,26 +513,29 @@ pub const Instruction = union(enum) { |
| 488 | 513 | }; |
| 489 | 514 | } |
| 490 | 515 | |
| 491 | | fn format2c(a: u1, cond: u4, op2: u3, cc1: u1, cc0: u1, p: u1, disp: i21) Instruction { |
| 516 | fn format2c(annul: bool, cond: u4, op2: u3, ccr: CCR, pt: bool, disp: i21) Instruction { |
| 492 | 517 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 493 | 518 | assert(disp % 4 == 0); |
| 494 | 519 | |
| 495 | 520 | // Discard the last two bits since those are implicitly zero. |
| 496 | 521 | const udisp = @truncate(u19, @bitCast(u21, disp) >> 2); |
| 522 | |
| 523 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) > 1); |
| 524 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 497 | 525 | return Instruction{ |
| 498 | 526 | .format_2c = .{ |
| 499 | | .a = a, |
| 527 | .a = @boolToInt(annul), |
| 500 | 528 | .cond = cond, |
| 501 | 529 | .op2 = op2, |
| 502 | | .cc1 = cc1, |
| 503 | | .cc0 = cc0, |
| 504 | | .p = p, |
| 530 | .cc1 = ccr_cc1, |
| 531 | .cc0 = ccr_cc0, |
| 532 | .p = @boolToInt(pt), |
| 505 | 533 | .disp19 = udisp, |
| 506 | 534 | }, |
| 507 | 535 | }; |
| 508 | 536 | } |
| 509 | 537 | |
| 510 | | fn format2d(a: u1, rcond: u3, op2: u3, p: u1, rs1: Register, disp: i18) Instruction { |
| 538 | fn format2d(annul: bool, rcond: RCondition, op2: u3, pt: bool, rs1: Register, disp: i18) Instruction { |
| 511 | 539 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 512 | 540 | assert(disp % 4 == 0); |
| 513 | 541 | |
| ... | ... | @@ -518,10 +546,10 @@ pub const Instruction = union(enum) { |
| 518 | 546 | const udisp_lo = @truncate(u14, udisp & 0b0011_1111_1111_1111); |
| 519 | 547 | return Instruction{ |
| 520 | 548 | .format_2a = .{ |
| 521 | | .a = a, |
| 522 | | .rcond = rcond, |
| 549 | .a = @boolToInt(annul), |
| 550 | .rcond = @enumToInt(rcond), |
| 523 | 551 | .op2 = op2, |
| 524 | | .p = p, |
| 552 | .p = @boolToInt(pt), |
| 525 | 553 | .rs1 = rs1.enc(), |
| 526 | 554 | .d16hi = udisp_hi, |
| 527 | 555 | .d16lo = udisp_lo, |