- vpternlogd của AVX-512 là một lệnh SIMD cho phép chọn logic Boolean bitwise bất kỳ với ba đầu vào bằng một giá trị tức thời 8 bit và thực thi trong một lần
- Điểm cốt lõi không phải là ghi nhớ các biểu thức logic phức tạp, mà là xem
#imm8 như một bảng tra cứu cho 8 trường hợp của ba đầu vào A/B/C
- Blitter của Amiga năm 1985 cũng chỉ định tổ hợp logic theo cùng cách, với ba nguồn bitmap và một minterm 8 bit; với masked sprite,
0xE2 thường được dùng
- Nếu đọc 8 bit của cột kết quả từ dưới lên trên, ta sẽ có giá trị tức thời, nên các điều kiện như “chính xác hai trong ba đầu vào là 1” cũng có thể tạo trực tiếp bằng
0x68
- Ví dụ vpternlogd trong tài liệu Intel và
0xE2 quen thuộc của demoscene Amiga giao nhau, cho thấy lệnh SIMD hiện đại và phần cứng đồ họa retro có chung một cảm quan thiết kế
vpternlogd của AVX-512
- vpternlogd là một lệnh logic tam phân bitwise nổi bật trong tài liệu trình bày thiết kế ISA AVX-512
- Nhận ba đầu vào A, B, C và có thể biểu diễn logic Boolean bất kỳ bằng một lệnh duy nhất
- Ví dụ:
(NOT A) OR ((NOT B) XOR (C AND A))
- Đầu vào có thể là thanh ghi 512 bit, nên có thể áp dụng logic phức tạp đồng thời lên toàn bộ 512 bit
- Thay vì liên tục thêm các lệnh chuyên dụng như
foo_and_a_or_not_b, nó xử lý nhiều kiểu logic bằng một lệnh linh hoạt và một giá trị tức thời 8 bit
VPTERNLOGD r0, r1, r3, #imm8
#imm8 quyết định hàm logic bit nào sẽ được thực hiện
- Nhiều tài liệu chỉ giải thích rằng giá trị tức thời “quyết định một hàm nhị phân cụ thể”, khiến cách tính thực tế khó nắm bắt một cách trực quan
Blitter Amiga và minterm
- Máy tính thập niên 1980 thường dùng chip tùy biến để xử lý đồ họa
- Blitter của Commodore Amiga 500 di chuyển đồ họa bitmap từ vị trí này sang vị trí khác, đồng thời áp dụng phép toán logic
- Nó xử lý tối đa ba nguồn bitmap, và phép toán logic giữa chúng được chỉ định bằng minterm, một giá trị 8 bit
- Về việc chọn tổ hợp logic bằng ba nguồn và một giá trị 8 bit, nó có cấu trúc giống vpternlogd
- Nhiều lập trình viên Amiga thường tái sử dụng các giá trị hay dùng thay vì tự hiểu cách tính minterm
- Khi xóa bộ đệm dùng
0x00
- Khi vẽ masked sprite dùng
0xE2
- “Amiga Hardware Reference Manual” năm 1989 giải thích cách tính minterm bằng các ký hiệu rối rắm, nên không giúp ích nhiều cho những người làm demo thời đó
Tính giá trị 8 bit như một bảng tra cứu
#imm8 hoặc minterm có thể được xem không phải là tổ hợp các toán tử logic, mà là một bảng tra cứu gồm 8 mục
- Ba đầu vào A, B, C mỗi đầu vào có thể là 0 hoặc 1, nên có 8 tổ hợp khả dĩ
- Chỉ cần điền trực tiếp kết quả mong muốn vào cột thứ tư
| A |
B |
C |
Kết quả mong muốn |
| 0 |
0 |
0 |
? |
| 0 |
0 |
1 |
? |
| 0 |
1 |
0 |
? |
| 0 |
1 |
1 |
? |
| 1 |
0 |
0 |
? |
| 1 |
0 |
1 |
? |
| 1 |
1 |
0 |
? |
| 1 |
1 |
1 |
? |
- Ví dụ, nếu muốn kết quả là 1 khi chính xác hai trong ba đầu vào là 1, hãy điền các giá trị thỏa điều kiện đó vào cột thứ tư
- Đọc 8 bit của cột kết quả từ dưới lên trên sẽ được
01101000, tức 0x68
- Vì vậy, hàm
0x68 đặt kết quả thành 1 khi chính xác hai trong ba đầu vào là 1
- Theo cùng cách, có thể lấy giá trị
#imm8 cần thiết cho bất kỳ hàm logic nào giữa ba nguồn
0xE2 của masked sprite
- Một trong những giá trị minterm rất phổ biến trên Amiga là
0xE2
- Giá trị này thường được dùng khi render masked 2D sprite
- A: bitmap sprite
- B: mask sprite
- C: background
- Điều kiện có thể được diễn đạt bằng logic chương trình đơn giản
- Nếu pixel mask B được đặt, kết quả là sprite A
- Nếu pixel mask B không được đặt, kết quả là background C
| A |
B |
C |
Kết quả mong muốn |
| 0 |
0 |
0 |
0 |
| 0 |
0 |
1 |
1 |
| 0 |
1 |
0 |
0 |
| 0 |
1 |
1 |
0 |
| 1 |
0 |
0 |
0 |
| 1 |
0 |
1 |
1 |
| 1 |
1 |
0 |
1 |
| 1 |
1 |
1 |
1 |
- Đọc cột kết quả từ dưới lên trên sẽ được
11100010, tức 0xE2
0xE2 là một giá trị minterm rất quen thuộc trong văn hóa demoscene Amiga
Mối liên hệ tình cờ với tài liệu Intel
1 bình luận
Các ý kiến trên Hacker News
Có một cách đơn giản để lấy giá trị tức thời từ biểu thức muốn tính. Ví dụ nếu muốn tính
(NOT A) OR ((NOT B) XOR (C AND A))thì có thể viết như~_MM_TERNLOG_A | (~_MM_TERNLOG_B ^ (_MM_TERNLOG_C & _MM_TERNLOG_A))Đúng nghĩa là biểu thức muốn tính, và nó được đánh giá thành giá trị tức thời từ các hằng
_MM_TERNLOG_A/B/Cđược định nghĩa trong header intrinsic của gcc và clang:typedef enum { _MM_TERNLOG_A = 0xF0, _MM_TERNLOG_B = 0xCC, _MM_TERNLOG_C = 0xAA } _MM_TERNLOG_ENUM;Với MSVC thì có thể tự định nghĩa
A = 0b11110000,B = 0b11001100,C = 0b10101010Chỉ nhìn tiêu đề, tôi tưởng ý là lệnh này không hoạt động đúng. Bài viết thực ra chỉ giải thích cách nó hoạt động
Tôi thời thiếu niên không viết “CRAP!” lên trang đó trong tài liệu phần cứng, nhưng đã nhìn chằm chằm vào nó rất lâu để cố hiểu
Cuối cùng, như hầu hết mọi người, tôi chỉ tìm Bobs và BLTCON0 để sao chép đơn giản rồi giả vờ như chưa từng thấy phần đó
Dù vậy vài năm sau tôi đạt A+ môn logic tính toán ở đại học, nên có lẽ sang chấn đó cũng giúp được phần nào
Nói về tiêu đề, “ternary logic” thường có nghĩa là logic có ba giá trị chân lý. Nhưng bài này nói về một lệnh compiler xử lý mọi cổng logic nhị phân nhận ba đầu vào
ternlogvà intrinsic cũng làternarylogic, nên dù hơi tiếc, tiêu đề vẫn phù hợpHơn nữa
bitwisephần nào đã giúp phân biệt với “logic ba giá trị”, cònternarycũng rất thường được dùng với nghĩa ba đầu vào.a ? b : ccũng thường được gọi là toán tử ba ngôi, và thực tếternlogcó thể mô phỏng phép toán ba ngôi này; bài viết cũng bàn đúng nội dung đótrinarychứ không phảiternaryTừ góc nhìn C++, JavaScript, Python, cách dùng phổ biến nhất có vẻ là biểu thức ba ngôi dạng
(a < b) ? 5 : 2. https://www.programiz.com/cpp-programming/ternary-operatorDù sao thì giả định nào cũng không quá quan trọng. Từ hoặc cụm từ vốn có nhiều nghĩa, và
ternarynghĩa là gồm ba phần, nên cũng đúng ở đâyternaryở đây không có nghĩa đóTrong C,
+nhận hai đầu vào nên là toán tử nhị phân, còn?:nhận ba đầu vào nên là toán tử ba ngôi. Chỉ vì nó là toán tử duy nhất trong C nên thường được gọi là “the ternary operator”, chứ bản chất không có gì đặc biệtvpternlogdtriển khai mọi toán tử ba ngôi theo bit nhận ba đầu vàoTôi tự hỏi có giống hàm
BitBltcủa Windows không. Ít nhất hình như nó đã có từ Windows 3.1, và tham sốopquyết định cách kết hợp nguồn, đích và mặt nạTôi nhớ có các tên mã như
BLACKNESS, tạo màu đen bất kể đầu vào, vàCOPY, sao chép nguồn sang đích.BLACKNESSvàWHITENESSnghe có nét thơ kỳ lạTheo những gì tôi nhớ từ Petzold, nó được triển khai bằng phần mềm, nhưng khi gọi thì opcode được chuyển thành assembly tùy chỉnh bên trong hàm, nên có vẻ là một trường hợp mã tự sửa đổi hiếm trong hệ điều hành Windows
BitBltban đầu dùng các “operation codes” 16-bit phức tạp, lưu phép toán nhị phân bằng ký pháp Ba Lan ngượcSau này họ thêm “operation index” chứa cùng thông tin trong 1 byte như Amiga, ngắn hơn và thanh nhã hơn. Hiện nay mỗi raster operation code chứa cả operation index lẫn operation code, nên phần mã hóa bị trùng lặp. https://devblogs.microsoft.com/oldnewthing/20180528-00/?p=98...
Giống cách FPGA triển khai hàm logic tùy ý bằng bảng tra cứu
Chỉ là ngoài các mục đích chuyên biệt như FPGA hoặc lệnh trong bài này, thường người ta không làm vậy. Thanh ghi tốc độ cao và RAM tĩnh đôi khi được làm bằng logic, nhưng thường thì tạo trực tiếp bằng transistor hơn là bằng cổng
74181cũng làm như vậyVào https://www.sandpile.org và tìm
VPTERNLOGtrên trang opcode 3 byte https://www.sandpile.org/x86/opc_3.htm, bạn cũng có thể thấy AVX512BITALG2, một biến thể masking byte/word có vẻ từng được Intel lên kế hoạchNgoài ra, từ toán hạng
Ibcó liên kết đến trang bảng chân trị ba ngôi chứa đủ 256 trường hợp: https://www.sandpile.org/x86/ternlog.htmViệc tài liệu chọn hàm
E2làm ví dụ có thể là vì trong các hàm boolean ba đầu vào, đó gần như là mux cơ bản và chuẩn nhất: nếuBthìA, nếu không thìCĐây là hàm phổ dụng, nên không nhất thiết phải là fan Amiga mới chọn. Tất nhiên, thực tế cũng có thể họ là fan
Một ví dụ khác về việc nhét phép toán theo bit vào số nguyên là mã ROP của GDI trong Win32: https://learn.microsoft.com/en-us/windows/win32/gdi/ternary-...
Tôi không có tài liệu phần cứng Amiga chính thức, mà xem cuốn “Mapping the Amiga”. Cuốn này giải thích cùng nội dung đó dài dòng hơn một chút
Tôi không nhớ lúc đó đã dùng minterm nào, nhưng nhờ cuốn này mà hình như tôi đã xoay xở triển khai được những thứ như shadebobs, bobs, vẽ đường 3D bằng XOR
Trang tương ứng trong Mapping the Amiga: https://archive.org/details/1993-thomson-randy-rhett-anderso...