| ... | @@ -446,6 +446,32 @@ pub const Instruction = union(enum) { | ... | @@ -446,6 +446,32 @@ pub const Instruction = union(enum) { |
| 446 | rs2: u5, | 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 | pub fn toU32(self: Instruction) u32 { | 475 | pub fn toU32(self: Instruction) u32 { |
| 450 | return @bitCast(u32, self); | 476 | return @bitCast(u32, self); |
| 451 | } | 477 | } |
| ... | @@ -462,17 +488,16 @@ pub const Instruction = union(enum) { | ... | @@ -462,17 +488,16 @@ pub const Instruction = union(enum) { |
| 462 | } | 488 | } |
| 463 | | 489 | |
| 464 | fn format2a(rd: Register, op2: u3, imm: i22) Instruction { | 490 | fn format2a(rd: Register, op2: u3, imm: i22) Instruction { |
| 465 | const umm = @bitCast(u22, imm); | | |
| 466 | return Instruction{ | 491 | return Instruction{ |
| 467 | .format_2a = .{ | 492 | .format_2a = .{ |
| 468 | .rd = rd.enc(), | 493 | .rd = rd.enc(), |
| 469 | .op2 = op2, | 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 | // In SPARC, branch target needs to be aligned to 4 bytes. | 501 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 477 | assert(disp % 4 == 0); | 502 | assert(disp % 4 == 0); |
| 478 | | 503 | |
| ... | @@ -480,7 +505,7 @@ pub const Instruction = union(enum) { | ... | @@ -480,7 +505,7 @@ pub const Instruction = union(enum) { |
| 480 | const udisp = @truncate(u22, @bitCast(u24, disp) >> 2); | 505 | const udisp = @truncate(u22, @bitCast(u24, disp) >> 2); |
| 481 | return Instruction{ | 506 | return Instruction{ |
| 482 | .format_2b = .{ | 507 | .format_2b = .{ |
| 483 | .a = a, | 508 | .a = @boolToInt(annul), |
| 484 | .cond = cond, | 509 | .cond = cond, |
| 485 | .op2 = op2, | 510 | .op2 = op2, |
| 486 | .disp22 = udisp, | 511 | .disp22 = udisp, |
| ... | @@ -488,26 +513,29 @@ pub const Instruction = union(enum) { | ... | @@ -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 | // In SPARC, branch target needs to be aligned to 4 bytes. | 517 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 493 | assert(disp % 4 == 0); | 518 | assert(disp % 4 == 0); |
| 494 | | 519 | |
| 495 | // Discard the last two bits since those are implicitly zero. | 520 | // Discard the last two bits since those are implicitly zero. |
| 496 | const udisp = @truncate(u19, @bitCast(u21, disp) >> 2); | 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 | return Instruction{ | 525 | return Instruction{ |
| 498 | .format_2c = .{ | 526 | .format_2c = .{ |
| 499 | .a = a, | 527 | .a = @boolToInt(annul), |
| 500 | .cond = cond, | 528 | .cond = cond, |
| 501 | .op2 = op2, | 529 | .op2 = op2, |
| 502 | .cc1 = cc1, | 530 | .cc1 = ccr_cc1, |
| 503 | .cc0 = cc0, | 531 | .cc0 = ccr_cc0, |
| 504 | .p = p, | 532 | .p = @boolToInt(pt), |
| 505 | .disp19 = udisp, | 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 | // In SPARC, branch target needs to be aligned to 4 bytes. | 539 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 512 | assert(disp % 4 == 0); | 540 | assert(disp % 4 == 0); |
| 513 | | 541 | |
| ... | @@ -518,10 +546,10 @@ pub const Instruction = union(enum) { | ... | @@ -518,10 +546,10 @@ pub const Instruction = union(enum) { |
| 518 | const udisp_lo = @truncate(u14, udisp & 0b0011_1111_1111_1111); | 546 | const udisp_lo = @truncate(u14, udisp & 0b0011_1111_1111_1111); |
| 519 | return Instruction{ | 547 | return Instruction{ |
| 520 | .format_2a = .{ | 548 | .format_2a = .{ |
| 521 | .a = a, | 549 | .a = @boolToInt(annul), |
| 522 | .rcond = rcond, | 550 | .rcond = @enumToInt(rcond), |
| 523 | .op2 = op2, | 551 | .op2 = op2, |
| 524 | .p = p, | 552 | .p = @boolToInt(pt), |
| 525 | .rs1 = rs1.enc(), | 553 | .rs1 = rs1.enc(), |
| 526 | .d16hi = udisp_hi, | 554 | .d16hi = udisp_hi, |
| 527 | .d16lo = udisp_lo, | 555 | .d16lo = udisp_lo, |